You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
Lifetimes are Rust's way of ensuring that references are always valid. Smart pointers provide additional capabilities beyond regular references — like heap allocation, reference counting, and interior mutability.
Every reference in Rust has a lifetime — the scope for which the reference is valid. Most of the time, lifetimes are inferred. Sometimes you need to annotate them explicitly.
// This will not compile — r references x, but x does not live long enough
let r;
{
let x = 5;
r = &x; // ERROR: x does not live long enough
}
println!("{r}");
Lifetime annotations describe the relationship between the lifetimes of multiple references. They do not change how long values live.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
The annotation 'a says: "the returned reference will be valid for at least as long as the shorter of x and y."
| Annotation | Meaning |
|---|---|
&'a T | A reference with lifetime 'a |
&'a mut T | A mutable reference with lifetime 'a |
'static | The reference lives for the entire program duration |
The compiler infers lifetimes in common patterns so you do not need to annotate them. These are the elision rules:
fn foo<'a, 'b>(x: &'a str, y: &'b str)fn foo<'a>(x: &'a str) -> &'a str&self or &mut self, the lifetime of self is assigned to all output lifetimes// No annotations needed — rule 2 applies
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &byte) in bytes.iter().enumerate() {
if byte == b' ' {
return &s[0..i];
}
}
s
}
If a struct holds references, it needs lifetime annotations:
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn announce_and_return(&self, announcement: &str) -> &str {
println!("Attention: {announcement}");
self.part // elision rule 3 applies
}
}
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().unwrap();
let excerpt = ImportantExcerpt {
part: first_sentence,
};
'static means the reference lives for the entire program:
let s: &'static str = "I live forever"; // string literals are 'static
Tip: Do not default to
'staticto "fix" lifetime errors. It is usually the wrong solution. Understand the actual lifetimes involved and annotate accordingly.
Smart pointers are data structures that act like pointers but have additional metadata and capabilities. They implement the Deref and Drop traits.
Box<T> allocates data on the heap:
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.