Rust

Lesson 02

Lifetimes for returned data

Return borrowed data only when the lifetime is tied to an input, instead of returning references to local values.

Good Code

src/review_lookup.rs
pub fn first_approved<'a>(reviews: &'a [Review]) -> Option<&'a Review> {
    // The returned reference can only live as long as the input slice.
    reviews.iter().find(|review| review.approved)
}

Bad Code

review_lookup.rs
pub fn first_approved_title(reviews: &[Review]) -> &str {
    let title = reviews
        .iter()
        .find(|review| review.approved)
        .map(|review| review.title.clone())
        .unwrap_or_default();

    // Returning a reference to local storage cannot outlive this function.
    title.as_str()
}

Review Notes

What to review

Good Code

The good version returns a reference to an element already owned by the input slice. The lifetime in the signature documents that relationship.

Bad Code

The bad version builds a local String and tries to return a borrowed &str from it. That reference would point to storage dropped at the end of the function.

Takeaways

  • A returned reference should point to data owned outside the function, with a lifetime that makes that relationship visible.