Course contentsShow
← Rust
Lesson 362 of 1,9104. Lifetimes and Advanced OwnershipFree lesson

Trait Bounds on Lifetimes

Create trait bounds that enforce specific lifetime relationships between implemented types.

In this lesson, you will learn how to enforce specific lifetime relationships between types when using trait bounds.

The Problem of Lifetime Mismatch

Sometimes, a generic type parameter needs to implement a trait, but the data inside that type has its own lifetime constraints. For example, if you have a struct that holds a reference, you need to ensure that the lifetime of that reference is valid for as long as the struct itself exists.

Normally, T: Display tells the compiler, "T must implement the Display trait." But what if T is a reference, like &'a str? We need a way to tell the compiler that the generic T must not only implement a trait but also satisfy a specific lifetime requirement.

Adding Lifetime Bounds

You can specify these relationships directly in your trait bounds using the syntax T: 'a. This signifies that any references contained within T must live at least as long as the lifetime 'a.

Consider this function:

fn print_ref<'a, T>(item: T) 
where 
    T: std::fmt::Display + 'a 
{
    println!("Value: {}", item);
}

In the signature above, T: 'a acts as a guard. It guarantees that if T holds a reference, that reference will remain valid for the duration of 'a. Without this bound, the compiler might worry that T could contain a reference that expires before 'a finishes, leading to a dangling pointer.

Why use this?

This pattern is essential when you store generic types in a struct that has its own lifetime parameter. If your struct is defined as struct Holder<'a, T>, you often need T: 'a in your impl blocks. This ensures that the type T doesn't contain any references shorter than the lifetime of the Holder itself. It’s a way of synchronizing the "health" of your generic data with the "health" of the container holding it.

By constraining T to 'a, you are essentially saying: "Whatever is inside T must be just as long-lived as the context I’m putting it into."

Key Takeaway: Adding a lifetime bound to a trait (e.g., T: 'a) ensures that any references inside the type T are guaranteed to outlive the specified lifetime 'a.