liveBook · Manning

Lifetime

As explained in Idiomatic Rust

A Rust lifetime is a compile-time property describing how long a reference or borrow remains valid.

A Rust lifetime describes how long a reference or borrow remains valid. A named lifetime, such as 'a, lets the compiler trace a reference through a type or function signature. It resembles a generic parameter in its angle-bracket syntax, but it describes reference validity rather than a type. section 2.1.5

A struct that borrows a string

In `struct Dog<'a> { name: &'a str }`, the name field borrows a string. The referenced string must remain valid for at least as long as the Dog value that holds it. section 2.1.5

Not every reference needs a written lifetime parameter. A method returning `&str` while taking `&self` can have its returned reference’s lifetime inferred from `self`. A function that only prints its `&str` argument is likewise shown both with `s: &str` and with an explicit `s: &'a str`. section 2.1.5 section 3.2.4

The special lifetime `'static` lasts for the duration of the program. String literals have this lifetime, so a function returning a string literal can spell its return type `&'static str` when that distinction is useful. section 2.1.5

Lifetimes also appear in iterator types. A borrowed linked-list iterator is written `Iter<'a, T>` with `PhantomData<&'a T>`; its `IntoIterator` implementation for `&'a LinkedList<T>` declares items of type `&'a T`. The mutable counterpart declares `&'a mut T`, while iteration that consumes the list yields owned `T` values. section 3.2.4

impl<'a, T> IntoIterator for &'a LinkedList<T> {
    type IntoIter = Iter<'a, T>;
    type Item = &'a T;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()       #1
    }
}
impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
    type IntoIter = IterMut<'a, T>;
    type Item = &'a mut T;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()      #2
    }
}
impl<T> IntoIterator for LinkedList<T> {     #3
    type IntoIter = IntoIter<T>;
    type Item = T;
    fn into_iter(self) -> Self::IntoIter {
        self.into_iter()        #4
    }
}

Compare the three `IntoIterator` implementations: borrowing the list, mutably borrowing it, and consuming it produce different item types. section 3.2.4

A lifetime annotation is not a substitute for checking an iterator’s implementation. The linked-list example eventually uses `unsafe` pointer conversions to return borrowed items; its signatures show the intended lifetimes, but those signatures alone do not establish that the conversions are safe. section 3.2.4

How Idiomatic Rust covers it

How deep it goes
Defines named lifetimes and `'static`, then applies annotations to borrowed iterator signatures without establishing the safety of their unsafe implementation.
Examples
Uses a borrowed string field, explicit and implicit function annotations, and linked-list iterators yielding references or owned values.
What it assumes
Assumes familiarity with Rust structs and references, while defining lifetime parameters and illustrating them with short signatures.
What you can do after
Apply it via Rust lifetime annotations to express borrowed fields and iterator items, while recognizing where inference suffices.
How it connects
Connects lifetimes to references, borrows, PhantomData, Iterator, IntoIterator, and ownership.

Also explained in

Compare how 8 books explain lifetime →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Idiomatic Rust. The section links point to the parts of the book it draws on.