Lifetime Elision
Lifetime elision lets you omit explicit 'a annotations in common patterns. The compiler applies three rules to infer relationships between references in function signatures.
Search across all documentation pages
Lifetime elision lets you omit explicit 'a annotations in common patterns. The compiler applies three rules to infer relationships between references in function signatures.
fn first_word(s: &str) -> &str {
s.split_whitespace().next().unwrap_or("")
}
fn main() {
let line = String::from("hello world");
println!("{}", first_word(&line));
}When to reach for this: Writing clean APIs without redundant 'a when the elision rules cover your signature.
struct Buffer<'a> { data: &'a [u8] }
impl<'a> Buffer<'a> {
fn get(&self, i: usize) -> Option<&u8> {
self.data.get(i)
}
fn slice(&self, range: std::ops::Range<usize>) -> Option<&[u8]> {
self.data.get(range)
}
}
fn main() {
let bytes = [1u8, 2, 3];
let buf = Buffer { data: &bytes };
println!("{:?}", buf.slice(0..2));
}What this demonstrates:
&self lifetime'a on get or slice signaturesbufimpl<'a> still required on struct with lifetime param&self), it is assigned to all outputs&self, output borrows from self// Elided: fn foo(s: &str) -> &str
// Desugared: fn foo<'a>(s: &'a str) -> &'a str
// Elided method: fn bar(&self, x: &str) -> &str
// Output borrows from self, not x (rule 3)&self - must annotatefn merge<'a>(&self, other: &'a str) -> &'a str etc.&self to &mut self subtly - Elision still applies but borrow rules differ. Fix: Re-check conflicts.| Alternative | Use When | Don't Use When |
|---|---|---|
Explicit 'a everywhere | Public API clarity | Simple methods where elision works |
Return owned String | Avoid lifetime coupling | Hot path needs borrow |
| Associated type output | Complex trait APIs | Simple fn suffices |
| GATs (advanced) | Iterator-like borrows | Stable simple signatures |
Closures infer lifetimes differently; elision rules are for fn/impl items.
No. Struct fields with references need explicit lifetime parameters.
Fails elision - multiple inputs, ambiguous output. Annotate: <'a>.
With &self and one other ref, output is from self per rule 3.
Async desugaring adds hidden lifetime on return Future; prefer 'static captures when possible.
Core elision rules stable; always verify with compiler on new signatures.
Sometimes. Public traits may document explicit lifetimes for readability.
Opaque return types have separate rules; borrows inside must still be valid.
rustc -Zunpretty=expanded or trust rust-analyzer hover on errors.
Whenever compiler rejects elided signature - next page is annotations.
'aStack 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