Lifetime Annotations
Explicit lifetime annotations tell the compiler how reference parameters and return values relate. They appear in function signatures, structs, enums, and trait impls.
Search across all documentation pages
Explicit lifetime annotations tell the compiler how reference parameters and return values relate. They appear in function signatures, structs, enums, and trait impls.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
fn main() {
let s = String::from("abcd");
let slice = longest(&s, "xy");
println!("{slice}");
}When to reach for this: Public APIs returning references, structs holding borrows, and resolving lifetime errors the compiler cannot elide.
struct Parser<'a> {
input: &'a str,
}
impl<'a> Parser<'a> {
fn new(input: &'a str) -> Self {
Self { input }
}
fn peek_word(&self) -> Option<&'a str> {
self.input.split_whitespace().next()
}
}
fn main() {
let text = String::from("hello world");
let p = Parser::new(&text);
println!("{:?}", p.peek_word());
}What this demonstrates:
impl<'a> repeats lifetime on impl block&'a str tied to parser's inputParser cannot outlive textfn split<'a>(s: &'a str, at: usize) -> (&'a str, &'a str) {
s.split_at(at)
}struct Pair<'a, 'b> {
first: &'a str,
second: &'b str,
}Each field may borrow from different sources.
fn copy_str<'a: 'b, 'b>(x: &'a str, y: &'b mut &str) {
*y = x;
}'a: 'b means 'a outlives 'b.
impl LifetimesLifetime params on impl must match struct/trait definition when methods return borrowed inner data.
'a to all related refs.'a, 'b when sources differ.impl struct with refs - Compile error on methods. Fix: impl<'a> Struct<'a>.fn inside impl without need - Noise. Fix: Use elision when compiler accepts.'a sets duration - You declare relationships; compiler verifies callsites. Fix: Read errors as constraint failures.| Alternative | Use When | Don't Use When |
|---|---|---|
| Owned fields | No borrow coupling | Need zero-copy view |
Generic AsRef<str> | Accept many string types | Return type still borrows |
Indices + parent Vec | Self-referential graphs | Simple substring API |
Arc<str> | Shared immutable storage | Single-owner string |
No. Elision and inference handle many cases. Annotate when required.
Yes: 'line, 'input. 'a is convention for first param.
Same rules. Exclusive borrow lifetime tied to owner.
Trait definitions may include lifetime params; impls must match.
Sometimes with lifetime elision on structs (rare). Often explicit is clearer.
Instructs inference to fill lifetime in ambiguous positions: Parser<'_>.
All inputs sharing output lifetime must live long enough - unify with 'a.
Closures usually infer. Move closures may need explicit where on outer fn.
Return futures may capture lifetimes; prefer owned captures in async when possible.
rust-analyzer shows required lifetimes in signature assists.
'static & Bounds - outlives boundsStack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 19, 2026