| # Lifetime Elision |
| |
| In order to make common patterns more ergonomic, Rust allows lifetimes to be |
| *elided* in function signatures. |
| |
| A *lifetime position* is anywhere you can write a lifetime in a type: |
| |
| <!-- ignore: simplified code --> |
| ```rust,ignore |
| &'a T |
| &'a mut T |
| T<'a> |
| ``` |
| |
| Lifetime positions can appear as either "input" or "output": |
| |
| * For `fn` definitions, `fn` types, and the traits `Fn`, `FnMut`, and `FnOnce`, |
| input refers to the types of the formal arguments, while output refers to |
| result types. So `fn foo(s: &str) -> (&str, &str)` has elided one lifetime in |
| input position and two lifetimes in output position. Note that the input |
| positions of a `fn` method definition do not include the lifetimes that occur |
| in the method's `impl` header (nor lifetimes that occur in the trait header, |
| for a default method). |
| |
| * For `impl` headers, all types are input. So `impl Trait<&T> for Struct<&T>` |
| has elided two lifetimes in input position, while `impl Struct<&T>` has elided |
| one. |
| |
| Elision rules are as follows: |
| |
| * Each elided lifetime in input position becomes a distinct lifetime |
| parameter. |
| |
| * If there is exactly one input lifetime position (elided or not), that lifetime |
| is assigned to *all* elided output lifetimes. |
| |
| * If there are multiple input lifetime positions, but one of them is `&self` or |
| `&mut self`, the lifetime of `self` is assigned to *all* elided output lifetimes. |
| |
| * Otherwise, it is an error to elide an output lifetime. |
| |
| Examples: |
| |
| <!-- ignore: simplified code --> |
| ```rust,ignore |
| fn print(s: &str); // elided |
| fn print<'a>(s: &'a str); // expanded |
| |
| fn debug(lvl: usize, s: &str); // elided |
| fn debug<'a>(lvl: usize, s: &'a str); // expanded |
| |
| fn substr(s: &str, until: usize) -> &str; // elided |
| fn substr<'a>(s: &'a str, until: usize) -> &'a str; // expanded |
| |
| fn get_str() -> &str; // ILLEGAL |
| |
| fn frob(s: &str, t: &str) -> &str; // ILLEGAL |
| |
| fn get_mut(&mut self) -> &mut T; // elided |
| fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded |
| |
| fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command // elided |
| fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded |
| |
| fn new(buf: &mut [u8]) -> BufWriter; // elided |
| fn new(buf: &mut [u8]) -> BufWriter<'_>; // elided (with `rust_2018_idioms`) |
| fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded |
| ``` |