Lifetimes

Function Lifetime Annotations

When a function returns a reference (&T, &mut T, &str, or a struct holding a reference), that returned reference must borrow from one of the function's reference parameters (or 'static). Function lifetime annotations (fn name<'a>(...) -> &'a ...) declare which input parameter(s) the returned reference is tied to.

Connecting Input and Output Lifetimes

Returning Data From One Specific Parameter

If a function takes two references (text and delimiter), uses delimiter only internally, and returns a sub-slice of text, only text shares 'a with the return type:

fn before_delimiter<'a>(text: &'a str, delimiter: &str) -> &'a str {
    match text.find(delimiter) {
        Some(idx) => &text[..idx],
        None => text,
    }
}

fn main() {
    let path = String::from("/usr/local/bin:/usr/bin");
    let first: &str;
    {
        let sep = String::from(":");
        first = before_delimiter(&path, &sep);
    } // `sep` drops here, but `first` only borrows `path`!
    println!("First entry: '{first}'");
}
First entry: '/usr/local/bin'

Returning Data That May Come From Either Parameter

When the returned reference could come from either a or b, both parameters must be annotated with 'a so the return value lives for the overlap of both inputs:

fn shorter<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.len() <= b.len() { a } else { b }
}

fn main() {
    println!("Shorter: '{}'", shorter("rust", "toolchain"));
}
Shorter: 'rust'

Compiler Enforcement of the Lifetime Contract

If a signature promises fn bad<'a>(x: &'a str, y: &str) -> &'a str (tying the output solely to x), but the body returns y, rustc rejects it at compile time:

// ❌ does not compile
fn mismatch<'a>(x: &'a str, y: &str) -> &'a str {
    let _ = x;
    y
}

fn main() {}
error: lifetime may not live long enough
 --> src/main.rs:4:5
  |
2 | fn mismatch<'a>(x: &'a str, y: &str) -> &'a str {
  |             --              - let's call the lifetime of this reference `'1`
  |             |
  |             lifetime `'a` defined here
3 |     let _ = x;
4 |     y
  |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

error: aborting due to 1 previous error