Challenge - 5 Problems
Rust Lifetime Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2:00remaining
What is the output of this Rust code with lifetime annotations?
Consider the following Rust code snippet. What will it print when run?
Rust
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); }
Attempts:
2 left
💡 Hint
Look at which string slice is longer and how lifetimes are used to ensure safety.
✗ Incorrect
The function longest returns the string slice with the longer length. "banana" is longer than "apple", so it prints "banana". The lifetime annotations ensure both inputs and output live long enough.
❓ Predict Output
intermediate2:00remaining
What error does this Rust code produce?
Analyze the following Rust code. What error will the compiler produce?
Rust
fn invalid_ref<'a>() -> &'a str { let s = String::from("hello"); &s } fn main() { let r = invalid_ref(); println!("{}", r); }
Attempts:
2 left
💡 Hint
Think about the lifetime of local variables and returned references.
✗ Incorrect
The function tries to return a reference to a local variable `s` which is dropped at the end of the function. This causes a compilation error: cannot return value referencing local variable `s`.
🔧 Debug
advanced2:00remaining
Does this Rust code compile and what does it print?
Examine the code below. What is the correct outcome?
Rust
fn choose_first<'a>(x: &'a str, y: &str) -> &'a str { x } fn main() { let s1 = String::from("hello"); let result; { let s2 = String::from("world"); result = choose_first(s1.as_str(), s2.as_str()); } println!("{}", result); }
Attempts:
2 left
💡 Hint
The function always returns `x`, and `y` is unused in the return value. Check if the borrow checker allows `s2` to be dropped early.
✗ Incorrect
No compilation error occurs because `choose_first` always returns the reference `x` (`s1.as_str()`), and `s1` lives until the end of `main`. The reference `y` (`s2.as_str()`) is borrowed only during the function call and not stored or returned, so dropping `s2` after the block is fine. The code compiles and prints "hello".
📝 Syntax
advanced2:00remaining
Which option correctly declares a function with lifetime annotations?
Choose the correct Rust function signature that returns a reference with a lifetime tied to the input reference.
Attempts:
2 left
💡 Hint
Remember the syntax for lifetime parameters in function signatures.
✗ Incorrect
Option A correctly declares a lifetime parameter `'a` and uses it for both input and output references. Option A has invalid syntax placing lifetime after &str. Option A uses `'a` without declaring it. Option A declares `'a` but input reference lacks it, causing mismatch.
🚀 Application
expert2:00remaining
How many items are in the resulting vector after this Rust code runs?
Given the following Rust code using lifetime annotations, how many elements does the vector `results` contain after execution?
Rust
fn collect_refs<'a>(inputs: Vec<&'a str>) -> Vec<&'a str> { let mut results = Vec::new(); for s in inputs { results.push(s); } results } fn main() { let s1 = String::from("one"); let s2 = String::from("two"); let s3 = String::from("three"); let inputs = vec![s1.as_str(), s2.as_str(), s3.as_str()]; let results = collect_refs(inputs); println!("{}", results.len()); }
Attempts:
2 left
💡 Hint
Consider the lifetimes of the strings and the references collected.
✗ Incorrect
All three strings live long enough for their references to be collected into the vector. The function collects all references without issue, so the resulting vector has 3 elements.