Lifetimes in Functions
In this page:
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
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));
}
Login to try C/C++/Java/PHP code in the editor
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
// 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));
}
Login to try C/C++/Java/PHP code in the editor
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
// 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());
}
Login to try C/C++/Java/PHP code in the editor
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
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));
}
Login to try C/C++/Java/PHP code in the editor
- Trying to return a reference from a function without any lifetime annotation when the compiler cannot infer which input it relates to.
- Assuming a function can return a reference to data created entirely inside itself -- that data does not outlive the function call.
- Forgetting that lifetime elision rules already cover many common single-reference-parameter functions automatically.
- 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: