SyntaxStudy
Sign Up
Rust Beginner 1 min read

Lifetime Annotations

Every reference in Rust has a lifetime — the scope during which the reference is valid. In most cases the compiler infers lifetimes automatically through a set of rules called lifetime elision. But when a function returns a reference whose lifetime depends on one of its parameters, or when a struct holds a reference, you must annotate lifetimes explicitly using the syntax `'a`, `'b`, etc. A lifetime annotation does not change how long a value lives; it expresses a relationship between the lifetimes of multiple references. When you write `fn longest<'a>(x: &'a str, y: &'a str) -> &'a str`, you are telling the compiler that the returned reference will be valid for at least as long as both inputs are valid. The compiler uses this to check that no caller creates a dangling reference. Structs that store references must also declare lifetime parameters. For example, `struct Excerpt<'a> { part: &'a str }` means that an `Excerpt` instance cannot outlive the string slice it holds. The special lifetime `'static` denotes a reference that is valid for the entire program duration — string literals have `'static` lifetime because they are embedded in the binary.
Example
// Lifetime annotation: the returned reference lives as long as
// the shorter-lived of x and y.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() >= y.len() { x } else { y }
}

// Struct holding a reference must declare a lifetime parameter
struct Excerpt<'a> {
    part: &'a str,
}

impl<'a> Excerpt<'a> {
    // Elided: &self has lifetime 'a, return shares 'a
    fn content(&self) -> &str {
        self.part
    }
}

fn main() {
    let s1 = String::from("long string is long");
    let result;
    {
        let s2 = String::from("xyz");
        result = longest(s1.as_str(), s2.as_str());
        println!("longest = {result}");
    }
    // result cannot be used here — s2 dropped above

    // Struct with a reference
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().unwrap();
    let ex = Excerpt { part: first_sentence };
    println!("excerpt: {}", ex.content());

    // 'static lifetime — valid for entire program
    let s: &'static str = "I am embedded in the binary";
    println!("{s}");
}