Lifetimes
Chapter 4 of Course 1 established that the borrow checker verifies references never outlive their data. Most of the time it does this invisibly. Occasionally — when a function's signature involves multiple references whose relationship to each other isn't clear from the code alone — the compiler needs an explicit hint. That hint is a lifetime annotation.
Why the Borrow Checker Sometimes Needs Help
This won't compile as written. The compiler can't determine which input's lifetime the returned reference should be tied to — it depends on which branch actually runs, and that's a runtime decision the compiler can't resolve at compile time without more information.
Lifetime Annotation Syntax
'a — an apostrophe plus a name, conventionally a single lowercase letter — is a lifetime parameter. This is a common early misconception worth stating plainly: lifetime annotations don't change how long anything lives. They describe a relationship that already exists in the code — here, that the returned reference is valid for at most as long as the shorter of x and y's actual lifetimes.
Lifetime Elision Rules
Most functions with references never need explicit lifetime annotations at all — the compiler applies three elision rules automatically:
- Each reference parameter gets its own lifetime.
- If there's exactly one input lifetime, it's assigned to every output lifetime.
- If one parameter is
&selfor&mut self(a method),self's lifetime is assigned to every output.
This is exactly why every &self method returning a reference back in Course 1 (Chapter 5) never needed an explicit lifetime — elision was silently handling it via rule 3 the entire time.
Struct Lifetimes
A struct that holds a reference, rather than an owned value, needs its own lifetime parameter:
This ties the struct instance's own validity to the reference it holds — if the referenced data were dropped before the struct itself, that's a compile error, exactly Course 1 Chapter 4's dangling-reference protection, now extended to cover structs.
The 'static Lifetime
'static is a special, reserved lifetime meaning "valid for the entire duration of the program." String literals are &'static str, since they're baked directly into the compiled binary and never get dropped.
| Situation | Annotation Needed? |
|---|---|
| One input reference, one output reference | No — elision rule 2 handles it |
| &self method returning a reference | No — elision rule 3 handles it |
| Multiple input references feeding one output | Yes — the compiler can't infer the relationship |
| A struct holding a reference | Yes — the struct needs its own lifetime parameter |
Lifetime Annotation ('a)
Describes an existing relationship between references' validity — never changes how long anything actually lives.
Elision Rules
Three automatic rules that cover the vast majority of real functions with no annotation required at all.
Struct Lifetimes
A struct storing a reference needs a lifetime parameter, tying the struct's validity to the data it borrows.
'static
Valid for the whole program's duration — string literals are the most common example.
'static on everything until the compiler stops complaining. This almost never actually solves the underlying ownership problem — it just forces data to live forever, which is often not what's actually wanted, and sometimes isn't even possible for the data in question. A 'static requirement appearing where it doesn't obviously belong is usually a sign the real fix lies elsewhere — often in how ownership is structured, not in the lifetime annotation itself.
Coding Challenges
Write a function shortest<'a>(x: &'a str, y: &'a str) -> &'a str returning whichever string slice is shorter, following this chapter's longest example as a template.
📄 View solutionDefine a struct FirstLine<'a> holding a single field line: &'a str, and a method fn announce(&self) -> &str that returns self.line. Explain, citing the specific elision rule, why announce needs no explicit lifetime annotation even though the struct itself does.
📄 View solutionExplain why changing a function's return type from &'a str to &'static str to silence a lifetime error is usually the wrong fix — describe what actually goes wrong for the caller if the underlying data genuinely isn't valid for the whole program's lifetime.
📄 View solutionChapter 1 Quick Reference
- 'a — a lifetime parameter; describes an existing relationship between references, never changes actual lifetimes
- Elision rule 1: each reference parameter gets its own lifetime
- Elision rule 2: exactly one input lifetime → assigned to all outputs
- Elision rule 3: a &self/&mut self parameter's lifetime → assigned to all outputs
- struct Name<'a> { field: &'a T } — a struct holding a reference needs its own lifetime parameter
- 'static — valid for the whole program's duration; string literals are &'static str
- Reaching for 'static to silence an error usually hides a real ownership-structure problem instead of fixing it
- Lifetimes are erased at compile time — zero runtime cost, purely a compiler-analysis tool
- Next chapter: Traits — trait definitions, default implementations, trait bounds, and a contrast with Go's interfaces