title: Lifetimes

Lifetimes are how Rust tracks how long references are valid. Most of the time the compiler infers them, but sometimes you need to annotate them explicitly to help the borrow checker understand the relationship between references.

The problem lifetimes solve

Without lifetimes, this would be ambiguous — does the returned reference point to x or y?

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

The compiler rejects this because it can’t guarantee the returned reference lives long enough.

Lifetime annotations

Lifetime annotations use a ' prefix (usually 'a, 'b, etc.). They don’t change how long anything lives — they describe the relationship between lifetimes:

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

This says: “the returned reference will be valid for at least as long as both x and y are valid.” The actual lifetime will be the shorter of the two.

Using the annotated function

let s1 = String::from("long string");
let result;
{
    let s2 = String::from("xy");
    result = longest(s1.as_str(), s2.as_str());
    println!("{result}");  // fine — both s1 and s2 are valid here
}
// println!("{result}");  // ERROR — s2 is dropped, result might point to it

Lifetime elision

Most functions don’t need explicit lifetime annotations because the compiler applies a set of elision rules automatically. These cover the common cases:

fn first_word(s: &str) -> &str { ... }
// equivalent to:
fn first_word<'a>(s: &'a str) -> &'a str { ... }

You only need to annotate when the compiler can’t figure it out on its own — usually when there are multiple input references and the return type is also a reference.

Lifetimes in structs

If a struct holds a reference, it needs a lifetime annotation:

struct Important<'a> {
    content: &'a str,
}
 
let novel = String::from("Call me Ishmael...");
let sentence = novel.split('.').next().unwrap();
let i = Important { content: sentence };

This says the Important struct cannot outlive the reference it holds in content.

The static lifetime

'static means the reference lives for the entire duration of the program. String literals are 'static because they’re baked into the binary:

let s: &'static str = "I live forever";