]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/lifetime-elision.md
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / src / doc / reference / src / lifetime-elision.md
CommitLineData
0531ce1d
XL
1# Lifetime elision
2
3Rust has rules that allow lifetimes to be elided in various places where the
4compiler can infer a sensible default choice.
5
6## Lifetime elision in functions
7
94b46f34 8In order to make common patterns more ergonomic, lifetime arguments can be
e1599b0c 9*elided* in [function item], [function pointer], and [closure trait] signatures.
0531ce1d 10The following rules are used to infer lifetime parameters for elided lifetimes.
94b46f34
XL
11It is an error to elide lifetime parameters that cannot be inferred. The
12placeholder lifetime, `'_`, can also be used to have a lifetime inferred in the
13same way. For lifetimes in paths, using `'_` is preferred. Trait object
14lifetimes follow different rules discussed
15[below](#default-trait-object-lifetimes).
0531ce1d
XL
16
17* Each elided lifetime in the parameters becomes a distinct lifetime parameter.
18* If there is exactly one lifetime used in the parameters (elided or not), that
19 lifetime is assigned to *all* elided output lifetimes.
20
21In method signatures there is another rule
22
23* If the receiver has type `&Self` or `&mut Self`, then the lifetime of that
24 reference to `Self` is assigned to all elided output lifetime parameters.
25
26Examples:
27
60c5eb7d
XL
28```rust
29# trait T {}
30# trait ToCStr {}
31# struct Thing<'a> {f: &'a i32}
32# struct Command;
33#
34# trait Example {
35fn print1(s: &str); // elided
36fn print2(s: &'_ str); // also elided
37fn print3<'a>(s: &'a str); // expanded
38
39fn debug1(lvl: usize, s: &str); // elided
40fn debug2<'a>(lvl: usize, s: &'a str); // expanded
41
42fn substr1(s: &str, until: usize) -> &str; // elided
43fn substr2<'a>(s: &'a str, until: usize) -> &'a str; // expanded
44
45fn get_mut1(&mut self) -> &mut dyn T; // elided
46fn get_mut2<'a>(&'a mut self) -> &'a mut dyn T; // expanded
47
48fn args1<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
49fn args2<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
50
51fn new1(buf: &mut [u8]) -> Thing<'_>; // elided - preferred
52fn new2(buf: &mut [u8]) -> Thing; // elided
53fn new3<'a>(buf: &'a mut [u8]) -> Thing<'a>; // expanded
54# }
55
56type FunPtr1 = fn(&str) -> &str; // elided
57type FunPtr2 = for<'a> fn(&'a str) -> &'a str; // expanded
58
59type FunTrait1 = dyn Fn(&str) -> &str; // elided
60type FunTrait2 = dyn for<'a> Fn(&'a str) -> &'a str; // expanded
61```
0531ce1d 62
60c5eb7d
XL
63```rust,compile_fail
64// The following examples show situations where it is not allowed to elide the
65// lifetime parameter.
0531ce1d 66
60c5eb7d
XL
67# trait Example {
68// Cannot infer, because there are no parameters to infer from.
69fn get_str() -> &str; // ILLEGAL
0531ce1d 70
60c5eb7d
XL
71// Cannot infer, ambiguous if it is borrowed from the first or second parameter.
72fn frob(s: &str, t: &str) -> &str; // ILLEGAL
73# }
0531ce1d
XL
74```
75
76## Default trait object lifetimes
77
78The assumed lifetime of references held by a [trait object] is called its
79_default object lifetime bound_. These were defined in [RFC 599] and amended in
94b46f34
XL
80[RFC 1156].
81
82These default object lifetime bounds are used instead of the lifetime parameter
83elision rules defined above when the lifetime bound is omitted entirely. If
84`'_` is used as the lifetime bound then the bound follows the usual elision
85rules.
0531ce1d
XL
86
87If the trait object is used as a type argument of a generic type then the
88containing type is first used to try to infer a bound.
89
90* If there is a unique bound from the containing type then that is the default
91* If there is more than one bound from the containing type then an explicit
92 bound must be specified
93
94If neither of those rules apply, then the bounds on the trait are used:
95
96* If the trait is defined with a single lifetime _bound_ then that bound is
97 used.
98* If `'static` is used for any lifetime bound then `'static` is used.
99* If the trait has no lifetime bounds, then the lifetime is inferred in
100 expressions and is `'static` outside of expressions.
101
60c5eb7d 102```rust
0531ce1d
XL
103// For the following trait...
104trait Foo { }
105
94222f64 106// These two are the same because Box<T> has no lifetime bound on T
60c5eb7d
XL
107type T1 = Box<dyn Foo>;
108type T2 = Box<dyn Foo + 'static>;
0531ce1d
XL
109
110// ...and so are these:
94b46f34
XL
111impl dyn Foo {}
112impl dyn Foo + 'static {}
0531ce1d
XL
113
114// ...so are these, because &'a T requires T: 'a
60c5eb7d
XL
115type T3<'a> = &'a dyn Foo;
116type T4<'a> = &'a (dyn Foo + 'a);
0531ce1d
XL
117
118// std::cell::Ref<'a, T> also requires T: 'a, so these are the same
60c5eb7d
XL
119type T5<'a> = std::cell::Ref<'a, dyn Foo>;
120type T6<'a> = std::cell::Ref<'a, dyn Foo + 'a>;
121```
0531ce1d 122
60c5eb7d
XL
123```rust,compile_fail
124// This is an example of an error.
125# trait Foo { }
126struct TwoBounds<'a, 'b, T: ?Sized + 'a + 'b> {
127 f1: &'a i32,
128 f2: &'b i32,
129 f3: T,
130}
131type T7<'a, 'b> = TwoBounds<'a, 'b, dyn Foo>;
132// ^^^^^^^
133// Error: the lifetime bound for this object type cannot be deduced from context
0531ce1d
XL
134```
135
94b46f34
XL
136Note that the innermost object sets the bound, so `&'a Box<dyn Foo>` is still
137`&'a Box<dyn Foo + 'static>`.
0531ce1d 138
60c5eb7d 139```rust
0531ce1d
XL
140// For the following trait...
141trait Bar<'a>: 'a { }
142
143// ...these two are the same:
60c5eb7d
XL
144type T1<'a> = Box<dyn Bar<'a>>;
145type T2<'a> = Box<dyn Bar<'a> + 'a>;
0531ce1d
XL
146
147// ...and so are these:
60c5eb7d
XL
148impl<'a> dyn Bar<'a> {}
149impl<'a> dyn Bar<'a> + 'a {}
0531ce1d
XL
150```
151
152## `'static` lifetime elision
153
154Both [constant] and [static] declarations of reference types have *implicit*
155`'static` lifetimes unless an explicit lifetime is specified. As such, the
156constant declarations involving `'static` above may be written without the
157lifetimes.
158
159```rust
160// STRING: &'static str
161const STRING: &str = "bitstring";
162
163struct BitsNStrings<'a> {
164 mybits: [u32; 2],
165 mystring: &'a str,
166}
167
168// BITS_N_STRINGS: BitsNStrings<'static>
94b46f34 169const BITS_N_STRINGS: BitsNStrings<'_> = BitsNStrings {
0531ce1d
XL
170 mybits: [1, 2],
171 mystring: STRING,
172};
173```
174
175Note that if the `static` or `const` items include function or closure
176references, which themselves include references, the compiler will first try
177the standard elision rules. If it is unable to resolve the lifetimes by its
178usual rules, then it will error. By way of example:
179
60c5eb7d
XL
180```rust
181# struct Foo;
182# struct Bar;
183# struct Baz;
184# fn somefunc(a: &Foo, b: &Bar, c: &Baz) -> usize {42}
0531ce1d 185// Resolved as `fn<'a>(&'a str) -> &'a str`.
60c5eb7d 186const RESOLVED_SINGLE: fn(&str) -> &str = |x| x;
0531ce1d
XL
187
188// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`.
60c5eb7d
XL
189const RESOLVED_MULTIPLE: &dyn Fn(&Foo, &Bar, &Baz) -> usize = &somefunc;
190```
0531ce1d 191
60c5eb7d
XL
192```rust,compile_fail
193# struct Foo;
194# struct Bar;
195# struct Baz;
196# fn somefunc<'a,'b>(a: &'a Foo, b: &'b Bar) -> &'a Baz {unimplemented!()}
0531ce1d
XL
197// There is insufficient information to bound the return reference lifetime
198// relative to the argument lifetimes, so this is an error.
60c5eb7d
XL
199const RESOLVED_STATIC: &dyn Fn(&Foo, &Bar) -> &Baz = &somefunc;
200// ^
201// this function's return type contains a borrowed value, but the signature
202// does not say whether it is borrowed from argument 1 or argument 2
0531ce1d
XL
203```
204
416331ca
XL
205[closure trait]: types/closure.md
206[constant]: items/constant-items.md
207[function item]: types/function-item.md
208[function pointer]: types/function-pointer.md
0531ce1d
XL
209[RFC 599]: https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md
210[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md
416331ca
XL
211[static]: items/static-items.md
212[trait object]: types/trait-object.md