@@ -6,40 +6,18 @@ compiler can infer a sensible default choice.
6
6
## Lifetime elision in functions
7
7
8
8
In 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.
10
12
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.
12
16
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
38
18
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.
43
21
44
22
Examples:
45
23
@@ -60,25 +38,38 @@ fn frob(s: &str, t: &str) -> &str; // ILLEGAL
60
38
fn get_mut(&mut self) -> &mut T; // elided
61
39
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
62
40
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
65
43
66
44
fn 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
68
49
50
+ type FunTrait = Fn(&str) -> &str; // elided
51
+ type FunTrait = for<'a> Fn(&'a str) -> &'a str; // expanded
69
52
```
70
53
71
54
## Defaults trait object lifetimes
72
55
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
75
58
[ RFC 1156] .
76
59
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
79
63
* 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.
82
73
83
74
``` rust,ignore
84
75
// For the following trait...
@@ -104,15 +95,10 @@ std::cell::Ref<'a, Foo + 'a>
104
95
struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
105
96
TwoBounds<'a, 'b, Foo> // Error: the lifetime bound for this object type cannot
106
97
// be deduced from context
107
-
108
98
```
109
99
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>`.
116
102
117
103
``` rust,ignore
118
104
// For the following trait...
@@ -133,48 +119,51 @@ TwoBounds<'a, 'b, Foo<'c>>
133
119
134
120
## ` 'static ` lifetime elision
135
121
136
- Both constant and static declarations of reference types have * implicit*
122
+ Both [ constant] and [ static] declarations of reference types have * implicit*
137
123
` 'static ` lifetimes unless an explicit lifetime is specified. As such, the
138
124
constant declarations involving ` 'static ` above may be written without the
139
- lifetimes. Returning to our previous example:
125
+ lifetimes.
140
126
141
127
``` 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
146
129
const STRING : & str = " bitstring" ;
147
130
148
131
struct BitsNStrings <'a > {
149
132
mybits : [u32 ; 2 ],
150
133
mystring : & 'a str ,
151
134
}
152
135
136
+ // BITS_N_STRINGS: BitsNStrings<'static>
153
137
const BITS_N_STRINGS : BitsNStrings = BitsNStrings {
154
- mybits : BITS ,
138
+ mybits : [ 1 , 2 ] ,
155
139
mystring : STRING ,
156
140
};
157
141
```
158
142
159
143
Note that if the ` static ` or ` const ` items include function or closure
160
144
references, 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:
164
147
165
148
``` rust,ignore
166
149
// Resolved as `fn<'a>(&'a str) -> &'a str`.
167
150
const RESOLVED_SINGLE: fn(&str) -> &str = ..
168
151
169
152
// 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 = ..
171
154
172
155
// 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 = ..
176
158
```
177
159
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
178
165
[ RFC 599 ] : https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md
179
166
[ 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