@@ -6,40 +6,18 @@ compiler can infer a sensible default choice.
66## Lifetime elision in functions
77
88In order to make common patterns more ergonomic, Rust allows lifetimes to be
9- * elided* in function signatures.
9+ * elided* in [ function item] , [ function pointer] and [ closure trait] signatures.
10+ The following rules are used to infer lifetime parameters for elided lifetimes.
11+ It is an error to elide lifetime parameters that cannot be infered.
1012
11- A * lifetime position* is anywhere you can write a lifetime in a type:
13+ * Each elided lifetime in the parameters becomes a distinct lifetime parameter.
14+ * If there is exactly one lifetime used in the parameters (elided or not), that
15+ lifetime is assigned to * all* elided output lifetimes.
1216
13- ``` rust,ignore
14- &'a T
15- &'a mut T
16- T<'a>
17- ```
18-
19- Lifetime positions can appear as either "input" or "output":
20-
21- * For ` fn ` definitions, input refers to the types of the formal arguments
22- in the ` fn ` definition, while output refers to
23- result types. So ` fn foo(s: &str) -> (&str, &str) ` has elided one lifetime in
24- input position and two lifetimes in output position.
25- Note that the input positions of a ` fn ` method definition do not
26- include the lifetimes that occur in the method's ` impl ` header
27- (nor lifetimes that occur in the trait header, for a default method).
28-
29- * In the future, it should be possible to elide ` impl ` headers in the same manner.
30-
31- Elision rules are as follows:
32-
33- * Each elided lifetime in input position becomes a distinct lifetime
34- parameter.
35-
36- * If there is exactly one input lifetime position (elided or not), that lifetime
37- is assigned to * all* elided output lifetimes.
17+ In method signatures there is another rule
3818
39- * If there are multiple input lifetime positions, but one of them is ` &self ` or
40- ` &mut self ` , the lifetime of ` self ` is assigned to * all* elided output lifetimes.
41-
42- * Otherwise, it is an error to elide an output lifetime.
19+ * If the receiver has type ` &Self ` or ` &mut Self ` , then the lifetime of that
20+ reference to ` Self ` is assigned to all elided output lifetime parameters.
4321
4422Examples:
4523
@@ -60,25 +38,38 @@ fn frob(s: &str, t: &str) -> &str; // ILLEGAL
6038fn get_mut(&mut self) -> &mut T; // elided
6139fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
6240
63- fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
64- fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
41+ fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
42+ fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
6543
6644fn new(buf: &mut [u8]) -> BufWriter; // elided
67- fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
45+ fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
46+
47+ type FunPtr = fn(&str) -> &str; // elided
48+ type FunPtr = for<'a> fn(&'a str) -> &'a str; // expanded
6849
50+ type FunTrait = Fn(&str) -> &str; // elided
51+ type FunTrait = for<'a> Fn(&'a str) -> &'a str; // expanded
6952```
7053
7154## Defaults trait object lifetimes
7255
73- The assumed lifetime of references held by a trait object is called its
74- * default object lifetime bound * . These were defined in [ RFC 599] and amended in
56+ The assumed lifetime of references held by a [ trait object] is called its
57+ _ default object lifetime bound _ . These were defined in [ RFC 599] and amended in
7558[ RFC 1156] .
7659
77- For traits that themselves have no lifetime parameters:
78- * If there is a unique bound from the containing type then that is the default.
60+ If the trait object is used as for a type argument of a generic type then the
61+ containing type is first used to try to infer a bound.
62+ * If there is a unique bound from the containing type then that is the default
7963* If there is more than one bound from the containing type then an explicit
80- bound must be specified.
81- * Otherwise the default bound is ` 'static ` .
64+ bound must be specified
65+
66+ Then the bounds on the trait are used:
67+
68+ * If the trait is defined with a single lifetime _ bound_ then that bound is
69+ used.
70+ * If ` 'static ` is used for any lifetime bound then ` 'static ` is used.
71+ * If the trait has no lifetime bounds, then the lifetime is inferred in
72+ expressions and is ` 'static ` outside of expressions.
8273
8374``` rust,ignore
8475// For the following trait...
@@ -104,15 +95,10 @@ std::cell::Ref<'a, Foo + 'a>
10495struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
10596TwoBounds<'a, 'b, Foo> // Error: the lifetime bound for this object type cannot
10697 // be deduced from context
107-
10898```
10999
110- The ` + 'static ` and ` + 'a ` refer to the default bounds of those kinds of trait
111- objects, and also to how you can directly override them. Note that the innermost
112- object sets the bound, so ` &'a Box<Foo> ` is still ` &'a Box<Foo + 'static> ` .
113-
114- For traits that have a single lifetime _ bound_ of their own then, instead of
115- infering 'static as the default bound, the bound on the trait is used instead
100+ Note that the innermost object sets the bound, so ` &'a Box<Foo> ` is still `&'a
101+ Box<Foo + 'static>`.
116102
117103``` rust,ignore
118104// For the following trait...
@@ -133,48 +119,51 @@ TwoBounds<'a, 'b, Foo<'c>>
133119
134120## ` 'static ` lifetime elision
135121
136- Both constant and static declarations of reference types have * implicit*
122+ Both [ constant] and [ static] declarations of reference types have * implicit*
137123` 'static ` lifetimes unless an explicit lifetime is specified. As such, the
138124constant declarations involving ` 'static ` above may be written without the
139- lifetimes. Returning to our previous example:
125+ lifetimes.
140126
141127``` rust
142- const BIT1 : u32 = 1 << 0 ;
143- const BIT2 : u32 = 1 << 1 ;
144-
145- const BITS : [u32 ; 2 ] = [BIT1 , BIT2 ];
128+ // STRING: &'static str
146129const STRING : & str = " bitstring" ;
147130
148131struct BitsNStrings <'a > {
149132 mybits : [u32 ; 2 ],
150133 mystring : & 'a str ,
151134}
152135
136+ // BITS_N_STRINGS: BitsNStrings<'static>
153137const BITS_N_STRINGS : BitsNStrings = BitsNStrings {
154- mybits : BITS ,
138+ mybits : [ 1 , 2 ] ,
155139 mystring : STRING ,
156140};
157141```
158142
159143Note that if the ` static ` or ` const ` items include function or closure
160144references, which themselves include references, the compiler will first try
161- the standard elision rules ([ see discussion in the nomicon] [ elision-nomicon ] ).
162- If it is unable to resolve the lifetimes by its usual rules, it will default to
163- using the ` 'static ` lifetime. By way of example:
145+ the standard elision rules. If it is unable to resolve the lifetimes by its
146+ usual rules, then it will error. By way of example:
164147
165148``` rust,ignore
166149// Resolved as `fn<'a>(&'a str) -> &'a str`.
167150const RESOLVED_SINGLE: fn(&str) -> &str = ..
168151
169152// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
170- const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = ..
153+ const RESOLVED_MULTIPLE: & Fn(&Foo, &Bar, &Baz) -> usize = ..
171154
172155// There is insufficient information to bound the return reference lifetime
173- // relative to the argument lifetimes, so the signature is resolved as
174- // `Fn(&'static Foo, &'static Bar) -> &'static Baz`.
175- const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = ..
156+ // relative to the argument lifetimes, so this is an error.
157+ const RESOLVED_STATIC: &Fn(&Foo, &Bar) -> &Baz = ..
176158```
177159
160+ [ closure trait ] : types.html#closure-types
161+ [ constant ] : items.html#constant-items
162+ [ function item ] : types.html#function-item-types
163+ [ function pointer ] : types.html#function-pointers
164+ [ implementation ] : items/implementations.html
178165[ RFC 599 ] : https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md
179166[ RFC 1156 ] : https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md
180- [ elision-nomicon ] : ../nomicon/lifetime-elision.html
167+ [ static ] : items.html#static-items
168+ [ trait object ] : types.html#trait-objects
169+ [ type aliases ] : items/type-aliases.html
0 commit comments