I want to re-answer my question here since it's still showing up high in search results and I feel I can explain better. Consider this code:
Rust Playground
struct Foo<'a> {
x: &'a i32,
y: &'a i32,
}
fn main() {
let x = 1;
let v;
{
let y = 2;
let f = Foo { x: &x, y: &y };
v = f.x;
}
println!("{}", *v);
}
And the error:
error[E0597]: `y` does not live long enough
--> src/main.rs:11:33
|
11 | let f = Foo { x: &x, y: &y };
| ^^ borrowed value does not live long enough
12 | v = f.x;
13 | }
| - `y` dropped here while still borrowed
14 | println!("{}", *v);
| -- borrow later used here
What's going on here?
- The lifetime of
f.x
has the requirement of being at least large enough to encompass the scope of x
up until the println!
statement (since it's initialized with &x
and then assigned to v
).
- The definition of
Foo
specifies that both f.x
and f.y
use the same generic lifetime 'a
, so the lifetime of f.y
must be at least as large as f.x
.
- But, that can't work, because we assign
&y
to f.y
, and y
goes out of scope before the println!
. Error!
The solution here is to allow Foo
to use separate lifetimes for f.x
and f.y
, which we do using multiple generic lifetime parameters:
Rust Playground
struct Foo<'a, 'b> {
x: &'a i32,
y: &'b i32,
}
Now the lifetimes of f.x
and f.y
aren't tied together. The compiler will still use a lifetime that's valid until the println!
statement for f.x
. But there's no longer a requirement that f.y
uses the same lifetime, so the compiler is free to choose a smaller lifetime for f.y
, such as one that is valid only for the scope of y
.