Rust Lifetime

In this tutorial, you will learn why lifetimes exist and how they keep your references safe.

Why Do Lifetimes Exist? #

In Rust, ownership and borrowing let us avoid memory bugs without a garbage collector.

But there’s still one tricky question: How does the compiler know that a reference is always valid?

That’s where lifetimes come in. A lifetime tells Rust how long a reference is valid.

The Core Rule #

A reference must never outlive the data it points to. If it could outlive, we’d get a dangling reference.

A Simple Borrow Example #

fn main() {
    let s1 = String::from("hello");
    let s2 = &s1; // borrow s1

    println!("s1 = {}, s2 = {}", s1, s2);
}Code language: Rust (rust)

This example works fine because both s1 and s2 are alive inside main, so no issue.

Reference Outliving Value Example #

fn main() {
    let r;
    {
        let s = String::from("hello");
        r = &s;   // ❌ ERROR: s does not live long enough
    }

    println!("{}", r);
}Code language: Rust (rust)

In this example:

  • s is created in the inner block.
  • When the block ends, s is dropped.
  • But r is still trying to reference it, which is not allowed.

Rust catches this error at compile time.

Lifetimes in Function Signatures #

If you use references in a function, Rust sometimes needs help knowing how long they should live. For example:

fn main() {
    let s1 = "hi";
    let s2 = "hello";

    let s3 = longest(&s1, &s2);

    println!("{}", s3);
}

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

This code won’t compile due to the error in the longest function. Rust doesn’t know whether the return reference comes from x or y.

However, you can fix it by adding a lifetime parameter 'a:

fn main() {
    let s1 = "hi";
    let s2 = "hello";

    let s3 = longest(&s1, &s2);

    println!("{}", s3);
}

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

In the new version:

  • 'a means: “the return value will live at least as long as both x and y.”
  • The compiler is happy.

Do I Always Need Lifetimes? #

No. Most of the time, Rust figures them out automatically (called lifetime elision rules). You only need to write them when Rust can’t decide unambiguously.

Summary #

  • Lifetimes tell Rust how long references are valid.
  • They prevent dangling references at compile time.
  • You don’t manage lifetimes manually and you just annotate them for the compiler.
  • Most cases are inferred automatically, but in functions with multiple references, you may need to specify them.
Was this Helpful ?