Rust Lifetimes Cheat Sheet
Explains lifetime annotations, lifetime elision rules, structs holding references, and how the borrow checker uses lifetimes to prevent dangling references.
Basic Lifetime Annotation
Annotating function signatures so the borrow checker can verify references.
// 'a says: the returned reference lives at least as long as both x and yfn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}fn main() { let s1 = String::from("long string"); let result; { let s2 = String::from("short"); result = longest(s1.as_str(), s2.as_str()); println!("Longest: {}", result); // must be used before s2 drops }}
Lifetime Elision Rules
When the compiler can infer lifetimes without explicit annotations.
- Rule 1- Each elided input reference gets its own distinct lifetime parameter
- Rule 2- If there's exactly one input lifetime, it's assigned to all elided output lifetimes
- Rule 3- If a parameter is &self or &mut self, its lifetime is assigned to all elided output lifetimes
- fn first_word(s: &str) -> &str- No annotations needed; elision infers the output borrows from s
- When elision fails- The compiler requires explicit 'a annotations when multiple refs could be the source
Structs Holding References
A struct cannot outlive the data it borrows.
// ImportantExcerpt cannot outlive the string slice it referencesstruct ImportantExcerpt<'a> { part: &'a str,}impl<'a> ImportantExcerpt<'a> { fn announce_and_return(&self, announcement: &str) -> &str { println!("Attention: {}", announcement); self.part }}let novel = String::from("Call me Ishmael. Some years ago...");let first_sentence = novel.split('.').next().unwrap();let excerpt = ImportantExcerpt { part: first_sentence };
Lifetimes with Generics
Combining lifetime parameters, generic types, and trait bounds.
use std::fmt::Display;// Combine a lifetime, a generic type, and a trait boundfn longest_with_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a strwhere T: Display,{ println!("Announcement! {}", ann); if x.len() > y.len() { x } else { y }}// T: 'a means: any references inside T must outlive 'astruct Wrapper<'a, T: 'a> { value: &'a T,}
The 'static Lifetime
The special lifetime meaning "valid for the whole program".
- 'static (reference)- The reference is valid for the entire duration of the program
- String literals- &str literals like "hello" are 'static; stored directly in the binary
- 'static bound on generics- Means T contains no non-'static references (owned data qualifies)
- Common misuse- Don't reach for 'static to "fix" a lifetime error; it often just hides a real ownership issue
Lifetime parameters don't change how long a value lives — they only describe constraints to the borrow checker so it can verify references don't outlive their data. If you're fighting lifetimes, consider whether owning the data (cloning, or using Rc) is simpler than threading references through.
Explore Topics
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance