Lifetimes

Lifetimes help the compiler understand how long references are valid.

Advanced⏱️ 45 min📚 Prerequisites: 1

Lifetimes

Lifetimes are generic parameters that tell the compiler how long references are valid.

Why Do We Need Lifetimes?

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

The compiler doesn't know which parameter the return reference points to, so it can't guarantee validity.

Lifetime Annotations

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

The 'a is a lifetime parameter indicating that both parameters and the return value have the same lifetime.

Lifetime Elision

In some cases, the compiler can automatically infer lifetimes:

RUST
fn first_word(s: &str) -> &str {  // Automatic lifetime
    // ...
}

In Structs

RUST
struct ImportantExcerpt<'a> {
    part: &'a str,
}

Code Examples

Basic Lifetime

Using lifetime annotations

RUST
fn main() {
    let string1 = String::from("long string is long");
    {
        let string2 = String::from("xyz");
        let result = longest(string1.as_str(), string2.as_str());
        println!("The longer string: {}", result);
    }
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Explanation:

The lifetime annotation `'a` indicates that the return reference is valid for at least as long as the shorter-lived parameter.

Struct Lifetime

Using lifetimes in structs

RUST
struct ImportantExcerpt<'a> {
    part: &'a str,
}
fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt {
        part: first_sentence,
    };
    println!("{}", i.part);
}

Explanation:

When a struct contains a reference field, lifetime annotations must be used. This guarantees that the reference is valid for at least as long as the struct instance.

Exercises

Lifetime Annotation

Fix this function with lifetime annotations!

Hard

Starter Code:

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