]>
Commit | Line | Data |
---|---|---|
8bb4bdeb | 1 | # Lifetime Elision |
c1a9b12d SL |
2 | |
3 | In order to make common patterns more ergonomic, Rust allows lifetimes to be | |
4 | *elided* in function signatures. | |
5 | ||
6 | A *lifetime position* is anywhere you can write a lifetime in a type: | |
7 | ||
136023e0 | 8 | <!-- ignore: simplified code --> |
c1a9b12d SL |
9 | ```rust,ignore |
10 | &'a T | |
11 | &'a mut T | |
12 | T<'a> | |
13 | ``` | |
14 | ||
15 | Lifetime positions can appear as either "input" or "output": | |
16 | ||
94222f64 XL |
17 | * For `fn` definitions, `fn` types, and the traits `Fn`, `FnMut`, and `FnOnce`, |
18 | input refers to the types of the formal arguments, while output refers to | |
c1a9b12d | 19 | result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in |
94222f64 XL |
20 | input position and two lifetimes in output position. Note that the input |
21 | positions of a `fn` method definition do not include the lifetimes that occur | |
22 | in the method's `impl` header (nor lifetimes that occur in the trait header, | |
23 | for a default method). | |
c1a9b12d | 24 | |
94222f64 XL |
25 | * For `impl` headers, all types are input. So `impl Trait<&T> for Struct<&T>` |
26 | has elided two lifetimes in input position, while `impl Struct<&T>` has elided | |
27 | one. | |
c1a9b12d SL |
28 | |
29 | Elision rules are as follows: | |
30 | ||
31 | * Each elided lifetime in input position becomes a distinct lifetime | |
32 | parameter. | |
33 | ||
34 | * If there is exactly one input lifetime position (elided or not), that lifetime | |
35 | is assigned to *all* elided output lifetimes. | |
36 | ||
37 | * If there are multiple input lifetime positions, but one of them is `&self` or | |
38 | `&mut self`, the lifetime of `self` is assigned to *all* elided output lifetimes. | |
39 | ||
40 | * Otherwise, it is an error to elide an output lifetime. | |
41 | ||
42 | Examples: | |
43 | ||
136023e0 | 44 | <!-- ignore: simplified code --> |
c1a9b12d SL |
45 | ```rust,ignore |
46 | fn print(s: &str); // elided | |
47 | fn print<'a>(s: &'a str); // expanded | |
48 | ||
7cac9316 XL |
49 | fn debug(lvl: usize, s: &str); // elided |
50 | fn debug<'a>(lvl: usize, s: &'a str); // expanded | |
c1a9b12d | 51 | |
7cac9316 XL |
52 | fn substr(s: &str, until: usize) -> &str; // elided |
53 | fn substr<'a>(s: &'a str, until: usize) -> &'a str; // expanded | |
c1a9b12d SL |
54 | |
55 | fn get_str() -> &str; // ILLEGAL | |
56 | ||
57 | fn frob(s: &str, t: &str) -> &str; // ILLEGAL | |
58 | ||
59 | fn get_mut(&mut self) -> &mut T; // elided | |
60 | fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded | |
61 | ||
9cc50fc6 SL |
62 | fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command // elided |
63 | fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded | |
c1a9b12d SL |
64 | |
65 | fn new(buf: &mut [u8]) -> BufWriter; // elided | |
94222f64 | 66 | fn new(buf: &mut [u8]) -> BufWriter<'_>; // elided (with `rust_2018_idioms`) |
c1a9b12d | 67 | fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded |
c1a9b12d | 68 | ``` |