@@ -5,10 +5,14 @@ compiler can infer a sensible default choice.
55
66## Lifetime elision in functions
77
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
99* elided* in [ function item] , [ function pointer] and [ closure trait] signatures.
1010The 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 ) .
1216
1317* Each elided lifetime in the parameters becomes a distinct lifetime parameter.
1418* If there is exactly one lifetime used in the parameters (elided or not), that
@@ -23,6 +27,7 @@ Examples:
2327
2428``` rust,ignore
2529fn print(s: &str); // elided
30+ fn print(s: &'_ str); // also elided
2631fn print<'a>(s: &'a str); // expanded
2732
2833fn debug(lvl: usize, s: &str); // elided
@@ -41,22 +46,27 @@ fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
4146fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
4247fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
4348
49+ fn new(buf: &mut [u8]) -> BufWriter<'_>; // elided - preferred
4450fn new(buf: &mut [u8]) -> BufWriter; // elided
4551fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
4652
4753type FunPtr = fn(&str) -> &str; // elided
4854type FunPtr = for<'a> fn(&'a str) -> &'a str; // expanded
4955
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
5258```
5359
5460## Default trait object lifetimes
5561
5662The assumed lifetime of references held by a [ trait object] is called its
5763_ 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.
6070
6171If the trait object is used as a type argument of a generic type then the
6272containing 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:
7888trait Foo { }
7989
8090// 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>
8393
8494// ...and so are these:
85- impl Foo {}
86- impl Foo + 'static {}
95+ impl dyn Foo {}
96+ impl dyn Foo + 'static {}
8797
8898// ...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)
91101
92102// 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>
95105
96106// This is an error:
97107struct 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
100110```
101111
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>` .
104114
105115``` rust,ignore
106116// For the following trait...
107117trait Bar<'a>: 'a { }
108118
109119// ...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>
112122
113123// ...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 {}
116126
117127// This is still an error:
118128struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b>
119- TwoBounds<'a, 'b, Foo<'c>>
129+ TwoBounds<'a, 'b, dyn Foo<'c>>
120130```
121131
122132## ` 'static ` lifetime elision
@@ -136,7 +146,7 @@ struct BitsNStrings<'a> {
136146}
137147
138148// BITS_N_STRINGS: BitsNStrings<'static>
139- const BITS_N_STRINGS : BitsNStrings = BitsNStrings {
149+ const BITS_N_STRINGS : BitsNStrings <' _ > = BitsNStrings {
140150 mybits : [1 , 2 ],
141151 mystring : STRING ,
142152};
@@ -152,11 +162,11 @@ usual rules, then it will error. By way of example:
152162const RESOLVED_SINGLE: fn(&str) -> &str = ..
153163
154164// 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 = ..
156166
157167// There is insufficient information to bound the return reference lifetime
158168// 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 = ..
160170```
161171
162172[ closure trait ] : types.html#closure-types
0 commit comments