@@ -5,10 +5,14 @@ compiler can infer a sensible default choice.
5
5
6
6
## Lifetime elision in functions
7
7
8
- In order to make common patterns more ergonomic, Rust allows lifetimes to be
8
+ In order to make common patterns more ergonomic, lifetime arguments can be
9
9
* elided* in [ function item] , [ function pointer] and [ closure trait] signatures.
10
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 inferred.
11
+ It is an error to elide lifetime parameters that cannot be inferred. The
12
+ placeholder lifetime, ` '_ ` , can also be used to have a lifetime inferred in the
13
+ same way. For lifetimes in paths, using ` '_ ` is preferred. Trait object
14
+ lifetimes follow different rules discussed
15
+ [ below] ( #default-trait-object-lifetimes ) .
12
16
13
17
* Each elided lifetime in the parameters becomes a distinct lifetime parameter.
14
18
* If there is exactly one lifetime used in the parameters (elided or not), that
@@ -23,6 +27,7 @@ Examples:
23
27
24
28
``` rust,ignore
25
29
fn print(s: &str); // elided
30
+ fn print(s: &'_ str); // also elided
26
31
fn print<'a>(s: &'a str); // expanded
27
32
28
33
fn debug(lvl: usize, s: &str); // elided
@@ -41,22 +46,27 @@ fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
41
46
fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
42
47
fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
43
48
49
+ fn new(buf: &mut [u8]) -> BufWriter<'_>; // elided - preferred
44
50
fn new(buf: &mut [u8]) -> BufWriter; // elided
45
51
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
46
52
47
53
type FunPtr = fn(&str) -> &str; // elided
48
54
type FunPtr = for<'a> fn(&'a str) -> &'a str; // expanded
49
55
50
- type FunTrait = Fn(&str) -> &str; // elided
51
- type FunTrait = for<'a> Fn(&'a str) -> &'a str; // expanded
56
+ type FunTrait = dyn Fn(&str) -> &str; // elided
57
+ type FunTrait = dyn for<'a> Fn(&'a str) -> &'a str; // expanded
52
58
```
53
59
54
60
## Default trait object lifetimes
55
61
56
62
The assumed lifetime of references held by a [ trait object] is called its
57
63
_ default object lifetime bound_ . These were defined in [ RFC 599] and amended in
58
- [ RFC 1156] . Default object lifetime bounds are used instead of the lifetime
59
- parameter elision rules defined above.
64
+ [ RFC 1156] .
65
+
66
+ These default object lifetime bounds are used instead of the lifetime parameter
67
+ elision rules defined above when the lifetime bound is omitted entirely. If
68
+ ` '_ ` is used as the lifetime bound then the bound follows the usual elision
69
+ rules.
60
70
61
71
If the trait object is used as a type argument of a generic type then the
62
72
containing type is first used to try to infer a bound.
@@ -78,45 +88,45 @@ If neither of those rules apply, then the bounds on the trait are used:
78
88
trait Foo { }
79
89
80
90
// These two are the same as Box<T> has no lifetime bound on T
81
- Box<Foo>
82
- Box<Foo + 'static>
91
+ Box<dyn Foo>
92
+ Box<dyn Foo + 'static>
83
93
84
94
// ...and so are these:
85
- impl Foo {}
86
- impl Foo + 'static {}
95
+ impl dyn Foo {}
96
+ impl dyn Foo + 'static {}
87
97
88
98
// ...so are these, because &'a T requires T: 'a
89
- &'a Foo
90
- &'a (Foo + 'a)
99
+ &'a dyn Foo
100
+ &'a (dyn Foo + 'a)
91
101
92
102
// std::cell::Ref<'a, T> also requires T: 'a, so these are the same
93
- std::cell::Ref<'a, Foo>
94
- std::cell::Ref<'a, Foo + 'a>
103
+ std::cell::Ref<'a, dyn Foo>
104
+ std::cell::Ref<'a, dyn Foo + 'a>
95
105
96
106
// This is an error:
97
107
struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
98
- TwoBounds<'a, 'b, Foo> // Error: the lifetime bound for this object type cannot
99
- // be deduced from context
108
+ TwoBounds<'a, 'b, dyn Foo> // Error: the lifetime bound for this object type
109
+ // cannot be deduced from context
100
110
```
101
111
102
- Note that the innermost object sets the bound, so ` &'a Box<Foo> ` is still `&'a
103
- Box<Foo + 'static>`.
112
+ Note that the innermost object sets the bound, so ` &'a Box<dyn Foo> ` is still
113
+ ` &'a Box<dyn Foo + 'static>` .
104
114
105
115
``` rust,ignore
106
116
// For the following trait...
107
117
trait Bar<'a>: 'a { }
108
118
109
119
// ...these two are the same:
110
- Box<Bar<'a>>
111
- Box<Bar<'a> + 'a>
120
+ Box<dyn Bar<'a>>
121
+ Box<dyn Bar<'a> + 'a>
112
122
113
123
// ...and so are these:
114
- impl<'a> Foo<'a> {}
115
- impl<'a> Foo<'a> + 'a {}
124
+ impl<'a> dyn Foo<'a> {}
125
+ impl<'a> dyn Foo<'a> + 'a {}
116
126
117
127
// This is still an error:
118
128
struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
119
- TwoBounds<'a, 'b, Foo<'c>>
129
+ TwoBounds<'a, 'b, dyn Foo<'c>>
120
130
```
121
131
122
132
## ` 'static ` lifetime elision
@@ -136,7 +146,7 @@ struct BitsNStrings<'a> {
136
146
}
137
147
138
148
// BITS_N_STRINGS: BitsNStrings<'static>
139
- const BITS_N_STRINGS : BitsNStrings = BitsNStrings {
149
+ const BITS_N_STRINGS : BitsNStrings <' _ > = BitsNStrings {
140
150
mybits : [1 , 2 ],
141
151
mystring : STRING ,
142
152
};
@@ -152,11 +162,11 @@ usual rules, then it will error. By way of example:
152
162
const RESOLVED_SINGLE: fn(&str) -> &str = ..
153
163
154
164
// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
155
- const RESOLVED_MULTIPLE: &Fn(&Foo, &Bar, &Baz) -> usize = ..
165
+ const RESOLVED_MULTIPLE: &dyn Fn(&Foo, &Bar, &Baz) -> usize = ..
156
166
157
167
// There is insufficient information to bound the return reference lifetime
158
168
// relative to the argument lifetimes, so this is an error.
159
- const RESOLVED_STATIC: &Fn(&Foo, &Bar) -> &Baz = ..
169
+ const RESOLVED_STATIC: &dyn Fn(&Foo, &Bar) -> &Baz = ..
160
170
```
161
171
162
172
[ closure trait ] : types.html#closure-types
0 commit comments