RUST / CHAPTER 11
Generic borrowing and lifetime relationships
AdvancedDescribe which input can support a returned reference.
By the end of this chapter
- Relate output borrows to input borrows
- Reject references to local owned data
- Use owned results when data must outlive inputs
The idea
A lifetime annotation describes a relationship among borrows; it does not keep a value alive longer. A function returning one of two borrowed inputs needs a contract that the output remains valid only while the relevant input relationship permits it. The compiler uses that contract to reject callers that would retain a reference beyond the lifetime of its data.
Returning a reference to a locally created String is invalid because that owned allocation is dropped when the function ends. Return the String itself when the caller should own the result. Lifetime annotations cannot repair a fundamentally dangling reference. Prefer the simplest signature that expresses the real ownership arrangement, and use compiler feedback to examine that arrangement rather than treating annotations as arbitrary syntax to silence errors.
fn longer<'a>(a:&'a str,b:&'a str)->&'a str{if a.len()>=b.len(){a}else{b}}
fn main(){let first=String::from("map");let second=String::from("loop");println!("{}",longer(&first,&second));}loop
The function returns a borrow of an input that is still alive in main; lengths here are byte lengths.
Try it yourself
Write a first_nonempty function that borrows one of two string slices and states their shared lifetime relationship.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING