Lifetime annotations help Rust know how long references should be valid. They prevent bugs by making sure data lives long enough.
Lifetime annotations in Rust
fn function_name<'a>(param: &'a Type) -> &'a Type { // function body }
Lifetime names start with an apostrophe, like 'a.
They tell Rust that the output reference lives at least as long as the input reference.
'a means the returned reference lives as long as both inputs.fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
'a ensures the reference is valid as long as the struct.struct ImportantExcerpt<'a> {
part: &'a str,
}'a ties the output to the input's lifetime.fn first_word<'a>(s: &'a str) -> &'a str { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[0..i]; } } &s[..] }
This program finds the longest string between two inputs using lifetime annotations to ensure safety.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } fn main() { let string1 = String::from("apple"); let string2 = "banana"; let result = longest(string1.as_str(), string2); println!("The longest string is: {}", result); }
Lifetime annotations do not change how long data lives; they just tell Rust about it.
Rust often figures out lifetimes automatically, but sometimes you must write them explicitly.
Using lifetime annotations helps avoid crashes from invalid references.
Lifetime annotations tell Rust how long references are valid.
They use apostrophe names like 'a to connect input and output lifetimes.
They help keep programs safe by preventing dangling references.
Practice
Solution
Step 1: Understand lifetime annotations role
Lifetime annotations tell Rust the scope of references to avoid dangling pointers.Step 2: Compare with other options
Other options describe unrelated concepts like type specification or memory management.Final Answer:
To tell Rust how long references are valid -> Option AQuick Check:
Lifetime annotations = reference validity [OK]
- Confusing lifetimes with types
- Thinking lifetimes manage memory directly
- Assuming lifetimes only affect return types
Solution
Step 1: Identify correct lifetime syntax
Lifetime parameters are declared with apostrophe before the name in angle brackets:'aand used in references.Step 2: Check each option
fn example<'a>(input: &'a str) -> &'a str correctly declares'aand uses it for input and output references. Others misuse syntax or place lifetime incorrectly.Final Answer:
fn example<'a>(input: &'a str) -> &'a str -> Option BQuick Check:
Lifetime syntax = fn example<'a>(input: &'a str) [OK]
- Placing lifetime after type instead of before
- Omitting lifetime declaration in angle brackets
- Using lifetime on non-reference types
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
fn main() {
let string1 = String::from("apple");
let string2 = "banana";
let result = longest(string1.as_str(), string2);
println!("{}", result);
}Solution
Step 1: Understand function longest behavior
The function returns the longer string slice between x and y.Step 2: Compare string lengths
"apple" has 5 letters, "banana" has 6 letters, so "banana" is longer and returned.Final Answer:
banana -> Option DQuick Check:
Longest string = banana [OK]
- Assuming compilation error due to lifetimes
- Confusing which string is longer
- Expecting runtime error from references
fn first_word<'a>(s: &str) -> &'a str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}Solution
Step 1: Check lifetime annotations on parameters and return
The parametershas no lifetime annotation, so Rust assigns an implicit lifetime. The return type has explicit lifetime'awhich is unrelated.Step 2: Understand lifetime mismatch
The return lifetime'amust be tied to the input lifetime to ensure safety. Here,'ais unrelated, causing a mismatch error.Final Answer:
Return type lifetime 'a does not match input lifetime -> Option CQuick Check:
Return lifetime must match input lifetime [OK]
- Forgetting to add lifetime to input parameter
- Assuming cloning is needed for slices
- Confusing &str and String return types
Solution
Step 1: Understand lifetime requirements for return
The returned reference must be valid as long as both inputs. Using a single lifetime'afor both inputs and output ensures this.Step 2: Analyze options
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str uses one lifetime parameter for both inputs and output, guaranteeing safety. fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str and C use different lifetimes, which can cause unsafe returns. fn longest(x: &str, y: &str) -> &str omits lifetimes, causing errors.Final Answer:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str -> Option AQuick Check:
Single lifetime for inputs and output [OK]
- Using different lifetimes for inputs and output
- Omitting lifetime annotations causing errors
- Assuming &str without lifetimes is enough
Ready to prove it?
Pass the test and this pattern moves unknown
