← Back to Rust Course | Chapter 12: Lifetimes | Lesson 2 of 6

Lifetime Annotation Syntax

Lifetime annotations are little labels, like 'a, that let you tell the compiler exactly how two references relate in age.

Basic Lifetime Annotation Syntax

A lifetime parameter, written as an apostrophe followed by a name like 'a, is declared in angle brackets just like a generic type parameter, then used to annotate reference types in the signature.

Example: Basic Lifetime Annotation Syntax

markup
fn first<'a>(x: &'a str, _y: &str) -> &'a str {
    x
}

fn main() {
    let a = String::from("first string");
    let b = String::from("second string");
    println!("{}", first(&a, &b));
}

Annotations Describe, Not Create, Relationships

Writing 'a on multiple parameters does not force them to live equally long -- it tells the compiler to check that the returned reference is valid for at least as long as the shortest of the input lifetimes.

Example: Annotations Describe, Not Create, Relationships

markup
fn choose_first<'a>(x: &'a str, y: &'a str) -> &'a str {
    if !x.is_empty() { x } else { y }
}

fn main() {
    let one = String::from("one");
    let two = String::from("two");
    println!("{}", choose_first(&one, &two));
}

Lifetime Annotations on Multiple References

When two parameters share the same lifetime label, the compiler ties their validity together for the purpose of checking the function's return value.

Example: Lifetime Annotations on Multiple References

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

fn main() {
    let x = String::from("hi");
    let y = String::from("hello");
    println!("{}", longer(&x, &y));
}

Naming Convention for Lifetimes

By convention, lifetime names are short and lowercase, typically starting with 'a, then 'b, 'c and so on for additional distinct lifetimes in the same signature.

Example: Naming Convention for Lifetimes

markup
fn pick_second<'a, 'b>(_first: &'a str, second: &'b str) -> &'b str {
    second
}

fn main() {
    let one = String::from("one");
    let two = String::from("two");
    println!("{}", pick_second(&one, &two));
}
Common Mistakes
  1. Assuming 'a in a lifetime annotation is a specific duration -- it's just a generic label the compiler uses to relate different references.
  2. Forgetting lifetime parameters are declared in angle brackets, similar to generic type parameters, e.g. fn foo<'a>(...).
  3. Adding lifetime annotations to a function that doesn't actually need them, when the compiler could infer the relationship on its own.
Chapter Summary
  • Lifetime parameters are written with an apostrophe, like 'a, and declared in angle brackets alongside generics.
  • An annotation like &'a str does not change how long the data lives -- it describes an existing relationship for the compiler to check.
  • Multiple references can share the same lifetime parameter when their validity is tied together.
  • Lifetime names are conventionally short, lowercase letters, starting with 'a, 'b, and so on.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.