Technology Sep 03, 2026 · 4 min read

🦀 Rust Master Class - Chapter 20: Advanced Lifetimes

🦀 Rust Master Class - Chapter 20: Advanced Lifetimes Visiting my grandfather's grave. The time we had wasn't enough, but it was what we had. Lifetimes in Rust aren't about duration — they're about knowing what outlives what. Advanced lifetimes in Rust extend beyond basic function...

DE
DEV Community
by Oludayo Adeoye
🦀 Rust Master Class - Chapter 20: Advanced Lifetimes

🦀 Rust Master Class - Chapter 20: Advanced Lifetimes

Visiting my grandfather's grave. The time we had wasn't enough, but it was what we had. Lifetimes in Rust aren't about duration — they're about knowing what outlives what.

Advanced lifetimes in Rust extend beyond basic function signatures to handle complex reference relationships, subtyping, and memory safety constraints. Based on the sources, the key concepts include the outlives relationship, lifetime bounds, variance, and anonymous lifetimes.

1. The Outlives Relationship

The foundational concept in advanced lifetimes is the outlives relationship. If one lifetime 'b lasts at least as long as another lifetime 'a, it is written as 'b: 'a . This relationship is essential for functions that take multiple references and need to guarantee that one piece of data does not expire before another that depends on it .

2. Lifetime Bounds

Lifetime bounds can be applied to generic types. The bound T: 'a means that the type T (and any references it contains) must last at least as long as the lifetime 'a .

  • Implied Bounds: In many cases, Rust assumes these bounds. For example, in a struct GenericWithLifetime<'a, T>, if it contains a field &'a T, the bound T: 'a is implied because the reference would be invalid if T didn't last at least as long as 'a .

Code Example:

struct GenericWithLifetime<'a, T> { 
    b: &'a T, // Implied bound: T must outlive 'a
}

// Explicit bound requirement
fn requires_lifetime_bound<'a, T: 'a>() {} 

[Source: 120, 121]

3. Subtyping and Variance

Variance describes how the subtyping relationship between lifetimes (e.g., 'static outliving 'a) translates to the subtyping relationship between complex types .

  • Covariance: If 'x: 'y, then T<'x> is a subtype of T<'y> .
    • Example: Because 'static outlives 'a, an immutable reference &'static str is a subtype of &'a str and can be passed to functions expecting the shorter lifetime .
  • Contravariance: If 'x: 'y, then T<'y> is a subtype of T<'x> .
    • Example: This primarily occurs in function arguments. A function type fn(&'a str) is a subtype of fn(&'static str) because a function that can handle a shorter lifetime can safely handle a longer one .
  • Invariance: If 'x: 'y, then T<'x> has no relationship with T<'y> .
    • Example: Mutable references (&mut T) are invariant. If they were covariant, you could accidentally store a short-lived reference into a long-lived container, causing a dangling pointer .

Code Example (Invariance Error):

// This function expects a mutable reference to a vector of references
fn accept_vec(str_vec: &mut Vec<&str>, s: &str) { 
    str_vec.push(s) 
} 

fn main() { 
    // Create a mutable variable
    let mut vec: Vec<&'static str> = vec!["", ""]; 
    // Create a new variable
    let non_static_str = &*String::from(""); 
    // This would fail if &mut was not invariant:
    // accept_vec(&mut vec, non_static_str); 
}

[Source: 124, 129]

4. Anonymous Lifetimes ('_)

Anonymous lifetimes are used when you want the compiler to infer (guess) the lifetime . This is allowed only when there is exactly one logical choice for the compiler to make .

  • Common Use Case: Inside an impl block, using &'_ str tells the compiler the lifetime must match the lifetime of self .

Code Example:

impl MyStruct {
    // The compiler guesses this matches the lifetime of 'self'
    fn get_ref(&self) -> &'_ str {
        "example"
    }
}

[Source: 125]

5. Lifetime Elision Rules

Advanced Rust relies on three rules to elide (omit) lifetimes in function signatures automatically:

  1. Each reference parameter gets its own unique lifetime parameter .
  2. If there is exactly one input lifetime, that lifetime is assigned to all output references .
  3. If there are multiple input lifetimes but one is &self or &mut self, the lifetime of self is assigned to all output references .

If a function does not satisfy these rules, lifetimes must be specified explicitly .

📖 Download the full PDF: https://drive.google.com/file/d/1GQGz8ztwPG4iqAgTDQ11Iw-YJXeKX6W2/view?usp=sharing

Part 20 of the Rust Master Class series — STEM EdTech | Automation Consulting | Rust Tutoring

RustLang #Programming #LearnToCode #STEM #EdTech

DE
Source

This article was originally published by DEV Community and written by Oludayo Adeoye.

Read original article on DEV Community
Back to Discover

Reading List