In this lesson, you will learn how to store references inside your custom structs by tying their lifetime to the data they point to.
The Problem: References and Ownership
In Rust, a struct typically owns its data. If you define a struct with a field like data: String, the struct is responsible for dropping that string. However, sometimes you don't want to own the data; you just want to "borrow" it. If you try to store a reference, like data: &str, the compiler will complain. It needs to know: "How long will this reference be valid?"
If the struct lives longer than the data it points to, your program would have a dangling pointer—a classic memory safety error. To solve this, we use lifetime annotations.
Linking Lifetimes with Generics
Just as you use <T> to make a struct generic over types, you use <'a> to make a struct generic over lifetimes. The lifetime annotation tells the compiler that the struct cannot outlive the reference it holds.
struct Book<'a> {
title: &'a str,
}
fn main() {
let title_string = String::from("Rust Programming");
let book = Book { title: &title_string };
println!("Reading: {}", book.title);
}
In this example, 'a is a placeholder for the lifetime of the string borrowed by title. By putting <'a> after the struct name and using it in the field type, you are telling the compiler: "This Book instance cannot exist longer than the reference stored in title."
The compiler verifies this by checking that title_string lives at least as long as book. If you tried to drop title_string while book was still in use, the compiler would stop you, preventing a potential crash.
Why is this "Generic"?
You can think of this as "parameterizing" your struct with a lifetime. When you instantiate Book, the Rust compiler automatically infers the specific lifetime for 'a based on the scope of the variable you pass in. This allows your struct to be flexible enough to hold references to data with different lifespans, as long as the constraints are satisfied.
Key Takeaway: Adding a lifetime parameter <'a> to a struct allows you to store references, forcing the compiler to ensure that the struct never outlives the data it references.