Reputation: 6472
The Rust Programming Language says:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
The function signature now tells Rust that for some lifetime
'a
, the function takes two parameters, both of which are string slices that live at least as long as lifetime'a
. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime'a
. In practice, it means that the lifetime of the reference returned by thelongest
function is the same as the smaller of the lifetimes of the references passed in. These relationships are what we want Rust to use when analyzing this code.
I don't get why it says:
In practice, it means that the lifetime of the reference returned by the
longest
function is the same as the smaller of the lifetimes of the references passed in.
Note the word "smaller". For both parameters and returned values, we specified 'a
which is the same. Why does the book say "smaller"? If that was the case, we would have different specifiers(a'
, b'
).
Upvotes: 1
Views: 196
Reputation: 2916
It's important to note that in the example, whatever is passed as x
and y
do not have to have identical lifetimes.
Let's rework the example to use &i32
which makes for easier demonstrations:
fn biggest<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
if x > y {
x
} else {
y
}
}
Now, given the following example:
fn main() {
let bigger;
let a = 64;
{
let b = 32;
bigger = biggest(&a, &b);
}
dbg!(bigger);
}
We have 3 different lifetimes:
bigger
which lives until the end of main
a
which lives until the end of main
b
which lives until the end of its blockNow lets take the description apart
the lifetime of the reference returned by the [...] function
In our case this would be bigger
, which lives until the end of main
smaller of the lifetimes of the references passed in
We passed in a
, which gets dropped at the end of main
, and b
, which gets dropped at the end of its block. Since b
gets dropped first, it is the "smaller" lifetime.
And sure enough, the compiler yells at us:
error[E0597]: `b` does not live long enough
--> src/main.rs:7:30
|
7 | bigger = biggest(&a, &b);
| ^^ borrowed value does not live long enough
8 | }
| - `b` dropped here while still borrowed
9 |
10 | dbg!(bigger);
| ------ borrow later used here
But if we move bigger
inside the block, and hence reduce its lifetime, the code compiles:
fn main() {
let a = 64;
{
let b = 32;
let bigger = biggest(&a, &b);
dbg!(bigger);
}
println!("This works!");
}
Now a
and b
still have different lifetimes but the code compiles since the the smaller of both lifetimes (b
's) is the same as bigger
's lifetime.
Did this help illustrate what "smaller" lifetime means?
Upvotes: 4