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

Lifetimes in Structs

A struct that holds a borrowed value needs its own age label too, so Rust can guarantee it never outlives what it's borrowing from.
Syntax
rust
struct Name<'a> {
    field: &'a str,
}

impl<'a> Name<'a> {
    fn method(&self) -> &str {
        self.field
    }
}

A Struct Holding a Reference

When a struct field is a reference, the struct itself needs a lifetime parameter, ensuring no instance of the struct can outlive the data it borrows.

Example: A Struct Holding a Reference

markup
// Define a struct `Excerpt` to group related fields together
struct Excerpt<'a> {
    text: &'a str,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `novel`, set to `String::from("Call me Ishmael. Some years ago...")`
    let novel = String::from("Call me Ishmael. Some years ago...");
    // Declare an immutable variable `first_sentence`, set to `novel.split('.').next().unwrap()`
    let first_sentence = novel.split('.').next().unwrap();
    // Declare an immutable variable `excerpt`, set to `Excerpt { text: first_sentence }`
    let excerpt = Excerpt { text: first_sentence };
    // Print "{}" to the console, substituting in `excerpt.text` (with a trailing newline)
    println!("{}", excerpt.text);
}

Methods on a Struct with a Lifetime

An impl block for a struct that has a lifetime parameter must declare and repeat that lifetime, letting methods work with the borrowed field just like any other.

Example: Methods on a Struct with a Lifetime

markup
// Define a struct `Excerpt` to group related fields together
struct Excerpt<'a> {
    text: &'a str,
}

// Implement methods on `Excerpt`
impl<'a> Excerpt<'a> {
    // Define the function `announce` taking `&self` and returning a String
    fn announce(&self) -> String {
        format!("Excerpt: {}", self.text)
    }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `source`, set to `String::from("Rust is reliable and fast")`
    let source = String::from("Rust is reliable and fast");
    // Declare an immutable variable `excerpt`, set to `Excerpt { text: &source[0..4] }`
    let excerpt = Excerpt { text: &source[0..4] };
    // Print "{}" to the console, substituting in `excerpt.announce()` (with a trailing newline)
    println!("{}", excerpt.announce());
}

Instances Cannot Outlive Their Data

The compiler guarantees that a struct instance holding a reference cannot be used after the data it references has gone out of scope, preventing dangling struct fields entirely.

Example: Instances Cannot Outlive Their Data

markup
// Define a struct `Wrapper` to group related fields together
struct Wrapper<'a> {
    value: &'a i32,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `number`, set to `42`
    let number = 42;
    // Declare an immutable variable `wrapped`, set to `Wrapper { value: &number }`
    let wrapped = Wrapper { value: &number };
    // Print "{}" to the console, substituting in `wrapped.value` (with a trailing newline)
    println!("{}", wrapped.value);
}

Avoiding Lifetimes with Owned Data

If a struct owns its data (using String instead of &str, for example) it needs no lifetime parameter at all, trading a small allocation cost for simpler code.

Example: Avoiding Lifetimes with Owned Data

markup
// Define a struct `OwnedExcerpt` to group related fields together
struct OwnedExcerpt {
    text: String,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `excerpt`, set to `OwnedExcerpt { text: String::from("No lifetime needed here") }`
    let excerpt = OwnedExcerpt { text: String::from("No lifetime needed here") };
    // Print "{}" to the console, substituting in `excerpt.text` (with a trailing newline)
    println!("{}", excerpt.text);
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Trying to store a reference in a struct field without declaring a lifetime parameter on the struct itself, which fails to compile.
  2. Assuming a struct holding a reference can outlive the data that reference points to -- the compiler enforces the opposite.
  3. Forgetting an impl block for a struct with a lifetime parameter must also repeat that lifetime, e.g. impl<'a> MyStruct<'a>.
Chapter Summary
  • A struct holding a reference field must declare a lifetime parameter, e.g. struct Excerpt<'a> { text: &'a str }.
  • An instance of such a struct cannot outlive the data its reference field points to.
  • impl blocks for a struct with a lifetime parameter must declare and repeat that same lifetime.
  • Storing owned data (like String instead of &str) avoids needing a lifetime parameter, at the cost of an extra allocation.
🔒

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.