Course contentsShow
← Rust
Lesson 112 of 1,9102. The Ownership ModelFree lesson

Subtyping and Lifetime Variance

Understand the conditions under which a longer-lived reference can be substituted for a shorter one.

In this lesson, you will learn how Rust safely allows you to use a "longer-lived" reference in a place that expects a "shorter-lived" one.

The Principle of Substitutability

In programming, subtyping is the ability to use a specific type where a more general type is expected. In Rust, lifetimes follow this logic. If you have a reference that lives for a long time (like 'static), you can safely pass it to a function that only requires the data to live for a shorter amount of time.

Think of it like this: if you promise your boss you will work for at least two hours, and they only ask you to work for one hour, you are fulfilling their requirement. The "longer" lifetime encompasses the "shorter" one.

Lifetime Subtyping in Action

Consider this scenario:

fn print_message(msg: &str) {
    println!("{}", msg);
}

let long_lived = "I live forever!"; // This has a 'static lifetime
let short_lived = String::from("I am temporary");

// The function expects a reference with SOME lifetime.
// We can pass a 'static reference because it's "longer" than needed.
print_message(long_lived);

// We can also pass the shorter reference, provided its scope is still active.
print_message(&short_lived);

Why Variance Matters

"Variance" describes how the relationship between two types (in this case, lifetimes) carries over when those types are used inside other structures (like a reference &'a T).

When we talk about covariant lifetimes, we are saying that if 'a is longer than 'b, then &'a T is a subtype of &'b T. This is why you can assign a reference that lives for a long time to a variable that has a much shorter expected lifetime. Rust allows this because it is always safe: if the data is guaranteed to exist for ten years, it is perfectly safe to treat it as if it exists for only ten minutes. You aren't creating a dangling pointer; you are simply narrowing your focus to a window of time where you know the data is still valid.

Key Takeaway: Because lifetimes are subtyped, a reference that lives longer can always be substituted for a reference that requires a shorter lifetime, as the longer one inherently satisfies the shorter requirement.