Lifetimes in Rust
Lifetimes describe the scope during which a reference is valid. The compiler uses lifetimes to prevent dangling references.
Elision rules (implicit lifetimes)
In many simple cases, Rust infers lifetimes so you don’t need to write them.
fn len(s: &str) -> usize { s.len() } // input ties to output implicitly
fn first<'a>(s: &'a str) -> &'a str { &s[..1] } // explicit equivalent
Elision rules tie output lifetimes to input references when unambiguous.
Explicit lifetimes
Add lifetime parameters when the compiler needs help relating inputs/outputs.
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() > b.len() { a } else { b }
}
Structs with references
Structs holding references must name lifetimes.
struct Slice<'a> { data: &'a [u8] }
impl<'a> Slice<'a> {
fn first(&self) -> Option<&'a u8> { self.data.first() }
}
Method receivers
&self and &mut self carry the struct’s lifetime implicitly.
'static lifetime
'static references live for the entire program (e.g., string literals). Avoid overusing 'static in APIs; it’s very restrictive.
let s: &'static str = "literal";
Lifetime bounds
Constrain generics with lifetime relationships.
fn foo<'a, T: 'a>(t: &'a T) { /* T outlives 'a */ }
Summary
- Elision covers common cases; add explicit lifetimes to relate inputs/outputs
- References in structs require lifetime parameters;
'staticmeans program-long - Use lifetime bounds to express outlives relationships on generics