| name | rust-lifetimes-borrowing |
| description | Master Rust ownership, borrowing, and lifetimes. Use when fighting the borrow checker, annotating lifetimes, understanding move semantics, working with references across scopes, or debugging lifetime errors. |
Rust Lifetimes & Borrowing
Comprehensive guide to Rust's ownership system, borrowing rules, and lifetime annotations based on The Rust Programming Language, The Rust Reference, and Common Rust Lifetime Misconceptions.
When to Use This Skill
- Borrow checker errors you don't understand
- Deciding between owned types and references
- Annotating lifetime parameters on structs/functions
- Understanding
'static, 'a, and elision rules
- Working with self-referential structures
- Debugging "does not live long enough" or "borrowed value dropped" errors
Ownership Rules
- Each value has exactly one owner.
- When the owner goes out of scope, the value is dropped.
- Ownership can be transferred (moved) but not duplicated (unless
Copy).
let s1 = String::from("hello");
let s2 = s1;
let x: i32 = 5;
let y = x;
Borrowing Rules
- You can have either one
&mut T or any number of &T — never both simultaneously.
- References must always be valid (no dangling).
fn calculate(data: &[u32]) -> u32 { data.iter().sum() }
fn push_item(v: &mut Vec<u32>, x: u32) { v.push(x); }
Lifetime Annotations
Lifetimes describe the scope during which a reference is valid. They don't change how long data lives — they help the compiler verify correctness.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
struct Excerpt<'a> {
part: &'a str,
}
Lifetime Elision Rules
The compiler infers lifetimes when unambiguous:
- Each reference parameter gets its own lifetime.
- If there is exactly one input lifetime, it is assigned to all output lifetimes.
- If one of the parameters is
&self or &mut self, its lifetime is assigned to all output lifetimes.
fn first_word(s: &str) -> &str { ... }
fn first_word<'a>(s: &'a str) -> &'a str { ... }
Common Misconceptions
1. T only contains owned types — WRONG
T is a superset of &T and &mut T. A generic T can be instantiated with reference types.
fn print_it<T: Display>(val: T) { println!("{val}"); }
print_it(&42);
2. T: 'static means "lives forever" — WRONG
T: 'static means T can live for the entire program if needed — it contains no short-lived borrows. Owned types like String, Vec<u8> all satisfy 'static.
fn spawn_thread<T: Send + 'static>(val: T) { ... }
spawn_thread(String::from("hi"));
3. &'a T and T: 'a are the same — WRONG
T: 'a — T outlives 'a (T's internal references live at least as long as 'a)
&'a T — a reference to T that is valid for 'a
4. Lifetimes grow/shrink at runtime — WRONG
Lifetimes are compile-time constructs. They describe static regions of code, not runtime durations.
5. Downgrading &mut to & is always safe — WRONG
Reborrowing as &*x is fine, but holding both the shared reborrow and the original &mut simultaneously is UB-adjacent (compiler rejects it).
6. Closures follow function elision rules — WRONG
Closures do NOT get the same elision rules as fn items. You often need explicit annotations or for<'a> bounds.
Variance
| Type | Variance in 'a | Variance in T |
|---|
&'a T | covariant | covariant |
&'a mut T | covariant | invariant |
Box<T> | — | covariant |
Cell<T> | — | invariant |
fn(T) -> U | — | contravariant in T, covariant in U |
Invariance means the lifetime/type cannot be shortened or lengthened — matters for mutable references and interior mutability.
Practical Patterns
Splitting borrows
let mut v = vec![1, 2, 3];
let (left, right) = v.split_at_mut(1);
left[0] = 10;
right[0] = 20;
Returning references from methods
impl MyStruct {
fn name(&self) -> &str { &self.name }
}
NLL (Non-Lexical Lifetimes)
Borrows end at the point of last use, not at the end of the lexical scope:
let mut v = vec![1, 2, 3];
let first = &v[0];
println!("{first}");
v.push(4);
Reference Map
references/ownership-moves.md — move semantics, Copy, Clone, drop order
references/borrowing-rules.md — borrow checker mechanics, reborrowing, two-phase borrows
references/lifetime-annotations.md — elision, explicit annotations, HRTB
references/common-misconceptions.md — the 10 misconceptions with solutions
Key References