Lifetimes: Ensuring Valid References
Lifetimes prevent dangling references. The compiler tracks how long references live and rejects code where a reference might outlive the data it points to.
// ERROR: returning reference to local data
// fn dangle() -> &String {
// let s = String::from("hi");
// &s // s dropped here - reference would dangle!
// }
// FIX: return owned String
fn no_dangle() -> String {
String::from("hi") // Ownership moves to caller
}
// When compiler cannot infer, annotate with 'a:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// 'a means: returned reference valid as long as shorter of x, y
fn main() {
let s1 = String::from("long string");
let result;
{
let s2 = String::from("xy");
result = longest(s1.as_str(), s2.as_str());
println!("{}", result); // OK: result used inside s2's scope
}
// println!("{}", result); // Would ERROR: s2 dropped
}Lifetimes in Structs
// Struct holding a reference needs lifetime annotation
struct Excerpt<'a> {
text: &'a str,
}
impl<'a> Excerpt<'a> {
fn content(&self) -> &str {
self.text // Lifetime elided - rule 3 applies
}
fn announce(&self, msg: &str) -> &str {
println!("Announcement: {}", msg);
self.text
}
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence;
{
let i = novel.find('.').unwrap_or(novel.len());
first_sentence = &novel[..i];
}
let exc = Excerpt { text: first_sentence };
println!("{}", exc.content());
}
// 'static: valid for entire program
// String literals are always 'static:
fn static_str() -> &'static str {
"I live forever"
}🎯 Practice
- Write fn longest_word<'a>(sentence: &'a str) -> &'a str returning the longest word
- Create struct StrPair<'a> { first: &'a str, second: &'a str } with a method returning the longer field
- Understand why this fails: fn bad<'a>() -> &'a str { let s = String::from("x"); &s }
🎉 Key Takeaways
- Lifetimes prevent dangling references - caught at compile time, zero runtime cost
- Most lifetimes are inferred via elision rules - annotate only when ambiguous
- 'a annotation means "this reference lives at least as long as 'a"
- Structs with reference fields must declare lifetime parameters
- 'static references are valid for the entire program lifetime