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:
&'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:
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