Lifetime Elision

In order to make common patterns more ergonomic, Rust allows lifetimes to beelided in function signatures.

A lifetime position is anywhere you can write a lifetime in a type:

  1. &'a T
  2. &'a mut T
  3. T<'a>

Lifetime positions can appear as either “input” or “output”:

  • For fn definitions, input refers to the types of the formal argumentsin the fn definition, while output refers toresult types. So fn foo(s: &str) -> (&str, &str) has elided one lifetime ininput position and two lifetimes in output position.Note that the input positions of a fn method definition do notinclude the lifetimes that occur in the method’s impl header(nor lifetimes that occur in the trait header, for a default method).

  • In the future, it should be possible to elide impl headers in the same manner.

Elision rules are as follows:

  • Each elided lifetime in input position becomes a distinct lifetimeparameter.

  • If there is exactly one input lifetime position (elided or not), that lifetimeis 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:

  1. fn print(s: &str); // elided
  2. fn print<'a>(s: &'a str); // expanded
  3. fn debug(lvl: usize, s: &str); // elided
  4. fn debug<'a>(lvl: usize, s: &'a str); // expanded
  5. fn substr(s: &str, until: usize) -> &str; // elided
  6. fn substr<'a>(s: &'a str, until: usize) -> &'a str; // expanded
  7. fn get_str() -> &str; // ILLEGAL
  8. fn frob(s: &str, t: &str) -> &str; // ILLEGAL
  9. fn get_mut(&mut self) -> &mut T; // elided
  10. fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
  11. fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
  12. fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
  13. fn new(buf: &mut [u8]) -> BufWriter; // elided
  14. fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded