Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lifetimes

Rule

Prefer lifetime elision and owned results; use explicit lifetimes when borrowing is the purpose of a view, parser, iterator, or zero-copy abstraction.

Why

Explicit lifetimes are useful for real borrowed views but add coupling when introduced only to avoid small clones or allocations.

Do

  • Rely on elision for ordinary borrowed inputs and accessors.
  • Use lifetime-bearing structs for genuine views into another value.
  • Name a lifetime when an output must clearly borrow from one input.
  • Use '_ when the local relationship needs no name.
  • Return borrowed iterators when that is the natural API.
  • Keep lifetime parameters out of unrelated types and layers.

Avoid

  • Do not build self-referential structs in ordinary code.
  • Do not name lifetimes that elision already communicates.
  • Do not make public APIs lifetime-heavy unless borrowing is central.
  • Do not add lifetimes solely to avoid a cheap owned result.

Public API Notes

Parsers, views, and zero-copy libraries may expose lifetimes deliberately. Ordinary APIs follow ownership policy.

Example

#![allow(unused)]
fn main() {
pub struct Token<'a> {
    text: &'a str,
}

impl Token<'_> {
    pub fn as_str(&self) -> &str {
        self.text
    }
}

pub fn first_token(input: &str) -> Option<Token<'_>> {
    input
        .split_whitespace()
        .next()
        .map(|text| Token { text })
}
}

Exceptions

  • Accept more lifetime complexity in measured hot paths where allocation matters.
  • Use borrowed adapter structs when their short relationship to a source is the abstraction.