Skip to main content

Lifetime

Most of the time, lifetimes are implicit and inferred, just like types are inferred. We must annotate the lifetimes when lifetimes of references could be related to different ways.

  1. Annotation syntax
  2. When to use lifetime or owned type values
  3. Lifetime elision
  4. Static lifetime

Examples

  • Function
foo<'a, 'b>
// In this case, the lifetime of foo cannot exceed that of either 'a or 'b.

// One input reference with lifetime `'a` which must live
// at least as long as the function.
fn print_one<'a>(x: &'a i32) {
println!("`print_one`: x is {}", x);
}

Lifetime in function

For a function with references in parameters and return values, the parameters are borrower and return values are borrowee. The variable borrower must live longer than the ref variable.

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}

fn main() {
let s1 = String::from("Long string is long");
{
let s2 = String::from("xyz");
let result = longest(s1.as_str(), s2.as_str());
println!("result: {}", result);
}
}

Ignoring elision, function signatures with lifetimes have a few constraints:

  • any reference must have an annotated lifetime.
  • any reference being returned must have the same lifetime as an input or be static.