Writing / Detail

Lifetimes: The "Timeline Contract"

2026.04.07
Technology
2789 Words
- Views
- Comments

Lifetimes are the most unique feature of Rust. You have probably never encountered them in JavaScript or TypeScript because the browser’s Garbage Collector handles all of this automatically behind the scenes.

Think of a Lifetime as a Timeline Contract. It’s Rust’s way of explicitly validating that a reference never points to “Ghost Data”—memory that has already been cleared.


🏗️ The 3-Step Narrative

1. The Dangling Reference (The Problem)

In JS, if you refer to an object and then it’s deleted, the Garbage Collector usually keeps it alive. In Rust, we don’t have a GC. If you keep a reference to something that died, your code crashes.

fn main() {
let r;
{
let x = 5;
r = &x; // ⬅️ x is created here
} // 🚮 x is dropped here
// println!("r: {r}"); ❌ Error: `x` does not live long enough
}

Rust’s compiler (The Borrow Checker) sees that x’s timeline is shorter than r’s timeline, so it refuses to run the code.

2. The Annotation (The Contract)

When a function takes two references and returns one, Rust needs help understanding which reference it’s returning so it can ensure the returned one isn’t dangling.

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

NOTE: The 'a Syntax

This isn’t “changing” how long things live. It’s just signing a contract that says: “The returned reference will live exactly as long as the shorter of the two input references.”

3. The Elision (The “Magic” Auto-Contract)

Luckily, you don’t always have to write these weird 'a symbols! Rust has built-in patterns called Elision Rules. If a function takes one reference and returns one, Rust automatically assumes they have the same timeline.

// You write this:
fn first_word(s: &str) -> &str { ... }
// The compiler "Autofills" the contract:
fn first_word<'a>(s: &'a str) -> &'a str { ... }

🔬 From the Official Book

⛓️ Structs with Lifetimes

Sometimes your data structure needs to “hold” a reference to something outside of it. In this case, the struct itself must sign the Timeline Contract.

struct ImportantExcerpt<'a> {
part: &'a str, // 📜 This part must live as long as the struct
}

💡 What Lifetimes Unlock

  • Zero Memory Corruption: By validating timelines at compile-time, Rust ensures that you will never have a dangling pointer or a random memory crash.
  • Fearless Refactoring: If you change how long a piece of data lives, the compiler will instantly tell you every place that now-broken reference is being used.
  • Static Analysis Power: Lifetimes give you the confidence of a Garbage-Collected language with the performance of a manually managed one.