snippetrustModeratepending
Rust Lifetime Annotations Cheat Sheet
Viewed 0 times
rustlifetimesborrow checkerreferencesannotationselision
Problem
Rust lifetime annotations are confusing, especially when functions return references or structs hold references.
Solution
Lifetime annotation patterns:
Elision rules (when you DON'T need annotations):
// Function returning a reference must specify lifetime
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// Struct holding references
struct Excerpt<'a> {
text: &'a str,
}
impl<'a> Excerpt<'a> {
fn level(&self) -> i32 { 3 } // No lifetime needed (elision)
fn announce(&self, msg: &str) -> &str {
// Returns &self lifetime (elision rule 3)
self.text
}
}
// Multiple lifetimes
fn first_or_default<'a, 'b>(s: &'a str, default: &'b str) -> &'a str {
if s.is_empty() { panic!("empty") } else { s }
}
// Static lifetime (lives for entire program)
let s: &'static str = "hello";
// Lifetime bounds on generics
fn print_it<T: std::fmt::Display + 'static>(val: T) {
println!("{}", val);
}Elision rules (when you DON'T need annotations):
- Each reference param gets its own lifetime
- If one input lifetime, output gets that lifetime
- If &self or &mut self, output gets self's lifetime
Why
Lifetimes ensure references are always valid. The borrow checker uses them to prevent dangling references at compile time, but the annotation syntax can be intimidating.
Gotchas
- 'static doesn't mean 'allocated forever' - it means 'can live forever' (owned data satisfies 'static)
- Lifetime annotations don't change how long references live - they describe existing relationships
Context
Working with references in Rust
Revisions (0)
No revisions yet.