Validating References with Lifetimes
In this chapter, we'll explore ensure references are valid for as long as needed.
Validating References with Lifetimes
Lifetimes are another kind of generic. Rather than ensuring a type has the behavior we want, lifetimes ensure references are valid as long as we need them.
Every reference has a lifetime—the scope for which that reference is valid. Most of the time, lifetimes are implicit and inferred. We annotate lifetimes when the lifetimes of references could be related in a few different ways.
Preventing Dangling References
The main aim of lifetimes is to prevent dangling references:
module main
fn main() -> void {
let r
{
let x = 5
r = &x // Error: `x` doesn't live long enough
}
println("r: ", r)
}Lifetime Annotation Syntax
Lifetime annotations don't change how long references live. They describe relationships between lifetimes:
&i32 // A reference
&'a i32 // A reference with an explicit lifetime
&'a mut i32 // A mutable reference with an explicit lifetimeLifetime Annotations in Functions
generic<'a>
fn longest(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
return x
} else {
return y
}
}This says: the returned reference will be valid as long as both input references are valid.
Lifetime Elision
The compiler can infer lifetimes in common patterns. These work without explicit lifetimes:
fn first_word(s: &str) -> &str { }The compiler applies elision rules to figure out lifetimes.
Lifetimes in Structs
Structs can hold references with lifetime annotations:
module main
generic<'a>
struct ImportantExcerpt {
part: &'a str,
}
fn main() -> void {
let novel = String::from("Call me Ishmael. Some years ago...")
let first_sentence = novel.split('.').next().unwrap()
let excerpt = ImportantExcerpt {
part: first_sentence,
}
}The Static Lifetime
The 'static lifetime means the reference can live for the entire program:
let s: &'static str = "I have a static lifetime."All string literals have 'static lifetime.
Summary
Generics, traits, and lifetimes work together:
generic<'a, T> where T: Display
fn longest_with_announcement(x: &'a str, y: &'a str, ann: T) -> &'a str {
println("Announcement! ", ann)
if x.len() > y.len() { x } else { y }
}Next, learn about Writing Automated Tests in Chapter 11.