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:
&'a T
&'a mut T
T<'a>
Lifetime positions can appear as either "input" or "output":
-
For
fndefinitions, input refers to the types of the formal arguments in thefndefinition, while output refers to result types. Sofn foo(s: &str) -> (&str, &str)has elided one lifetime in input position and two lifetimes in output position. Note that the input positions of afnmethod definition do not include the lifetimes that occur in the method'simplheader (nor lifetimes that occur in the trait header, for a default method). -
In the future, it should be possible to elide
implheaders in the same manner.
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
&selfor&mut self, the lifetime ofselfis 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<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded