Lifetime annotations guide the borrow checker. Consider the following function (which does not compile, because the borrow checker cannot work out what I mean):
use std::str::FromStr;
fn choose_a_string(which_one: &str, str1: &str, str2: &str) -> &str {
let choice = bool::from_str(which_one).unwrap_or_else(|_| {
let num = i32::from_str(which_one).unwrap_or(0);
num == 0
});
if choice {
str1
} else {
str2
}
}
Without lifetime annotations, it's unclear to the borrow checker what constraints apply to the lifetimes of the references. By adding lifetime annotations, I can make it clear:
fn choose_a_string<'retval>(
which_one: &'_ str,
str1: &'retval str,
str2: &'retval str,
) -> &'retval str {
(Rust Playground with lifetime annotations).
With the added annotations, the borrow checker can see that which_one
's lifetime is unrelated to the lifetime of the return value, and that both str1
and str2
need to be valid while the return value is alive.