← Back to Rust Course | Chapter 12: Lifetimes | Lesson 3 of 6

Lifetimes in Functions

When a function hands back a borrowed value, it has to explain which of its inputs that borrowed value actually came from.
Syntax
rust
fn name<'a>(x: &'a str, y: &'a str) -> &'a str {
    // body
}

Returning a Reference Tied to a Parameter

When a function might return either of two reference parameters, an explicit lifetime annotation tells the compiler the returned reference is valid for as long as both inputs are.

Example: Returning a Reference Tied to a Parameter

markup
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    // Check whether `x.len() > y.len() { x } else { y }`
    if x.len() > y.len() { x } else { y }
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `s1`, set to `String::from("short")`
    let s1 = String::from("short");
    // Declare an immutable variable `s2`, set to `String::from("a bit longer")`
    let s2 = String::from("a bit longer");
    // Print "{}" to the console, substituting in `longest(&s1, &s2)` (with a trailing newline)
    println!("{}", longest(&s1, &s2));
}

Lifetime Elision for Simple Functions

For functions with exactly one reference parameter and a reference return type, Rust's elision rules infer the lifetime automatically, so no explicit annotation is needed.

Example: Lifetime Elision for Simple Functions

markup
// Define the function `first_char` taking `s` and returning a string slice
fn first_char(s: &str) -> &str {
    &s[0..1]
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `word`, set to `"Rust"`
    let word = "Rust";
    // Print "{}" to the console, substituting in `first_char(word)` (with a trailing newline)
    println!("{}", first_char(word));
}

Why You Cannot Return a Reference to a Local Variable

A function can never validly return a reference to data it created locally, since that data is dropped when the function returns; the fix is to return an owned value instead.

Example: Why You Cannot Return a Reference to a Local Variable

markup
// Define the function `build_owned` with no parameters and returning a String
fn build_owned() -> String {
    // Declare an immutable variable `local`, set to `String::from("owned and returned safely")`
    let local = String::from("owned and returned safely");
    local
}

// Entry point: execution of the program starts here
fn main() {
    // Print "{}" to the console, substituting in `build_owned()` (with a trailing newline)
    println!("{}", build_owned());
}

Functions with Independent Lifetimes

When a function's return value only relates to one of several reference parameters, giving each parameter its own independent lifetime clarifies that relationship precisely.

Example: Functions with Independent Lifetimes

markup
fn describe<'a>(name: &'a str, _ignored: &str) -> &'a str {
    name
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `name`, set to `String::from("Rustacean")`
    let name = String::from("Rustacean");
    // Declare an immutable variable `other`, set to `String::from("unrelated")`
    let other = String::from("unrelated");
    // Print "{}" to the console, substituting in `describe(&name, &other)` (with a trailing newline)
    println!("{}", describe(&name, &other));
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Trying to return a reference from a function without any lifetime annotation when the compiler cannot infer which input it relates to.
  2. Assuming a function can return a reference to data created entirely inside itself -- that data does not outlive the function call.
  3. Forgetting that lifetime elision rules already cover many common single-reference-parameter functions automatically.
Chapter Summary
  • A function returning a reference must specify which parameter's lifetime the return value is tied to.
  • Lifetime elision rules let the compiler infer lifetimes automatically for many simple, common function shapes.
  • A function can never return a reference to purely local data -- it must return an owned value or a reference tied to a parameter.
  • When a function has multiple reference parameters and returns one of them conditionally, an explicit lifetime is usually required.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.