Hard15 minRust Fundamentals
UpdatedAug 4, 2026
Edit

Lifetimes and Borrow Checking

CONCEPTS:Rust Lifetimes

Question Variations

  • "When do Rust lifetime annotations become necessary?"
  • "Do lifetime annotations extend how long a value lives?"
  • "Why can't a function return a reference to a local variable?"
  • "What relationship does `'a` express in a function signature?"

Why This Is Asked

Lifetimes are often misunderstood as runtime durations or manual memory management. This question evaluates whether you can explain them as compile-time relationships and write signatures that prevent dangling references without over-annotating code.

Key Concepts

  • Lifetimes are checked at compile time and do not change runtime object lifetime.
  • The compiler infers most local lifetimes through lifetime elision rules.
  • Explicit annotations connect input and output reference validity relationships.
  • A reference can never outlive the value it refers to.

Question Variations

  • “When do Rust lifetime annotations become necessary?”
  • “Do lifetime annotations extend how long a value lives?”
  • “Why can’t a function return a reference to a local variable?”
  • “What relationship does 'a express in a function signature?”

Answers by Technology

+ Add Variant
RustImprove this answer ✏️

Expected Answer (Rust 1.97.1)

Lifetimes are compile-time annotations that describe relationships between references. They do not make data live longer; they let the borrow checker verify that every reference remains valid. Rust infers lifetimes in many common signatures, but an explicit parameter is needed when the returned reference might originate from more than one input reference.

In this signature, the returned reference is valid no longer than the shorter-lived of left and right:

fn longer<'a>(left: &'a str, right: &'a str) -> &'a str {
    if left.len() >= right.len() {
        left
    } else {
        right
    }
}

fn main() {
    let result = longer("alpha", "beta");
    assert_eq!(result, "alpha");
}

The annotation says the input references and output reference share a validity relationship. It does not require them to have exactly the same concrete duration.

Why It Matters

Lifetimes make APIs that return borrowed data safe without garbage collection. Understanding them helps you design clear ownership boundaries and recognize when returning an owned value is simpler than forcing a complex borrowed relationship.

Common Mistakes

  • Thinking 'a is a runtime timer: Lifetimes exist for compile-time checking and are normally erased from generated code.
  • Adding annotations to fix an invalid reference: An annotation cannot make a reference to dropped local data valid.
  • Assuming all lifetimes must be written explicitly: The compiler elides many common cases.

Follow-up Questions

  • Why can’t a function return &local_string? (Answer: The local string is dropped when the function returns, leaving a dangling reference.)
  • When might returning String be better than &str? (Answer: When the result must outlive the inputs or ownership is simpler for callers.)