I have this piece of code:
#[derive(Debug)]
struct Foo<'a> {
x: &'a i32,
}
impl<'a> Foo<'a> {
fn set(&mut self, r: &'a i32) {
self.x = r;
}
}
fn main() {
let v = 5;
let w = 7;
let mut f = Foo { x: &v };
println!("f is {:?}", f);
f.set(&w);
println!("now f is {:?}", f);
}
My understanding is that in the first borrow of the value of v
, the generic lifetime parameter 'a
on the struct declaration is filled in with the lifetime of the value of v
. This means that the resulting Foo
object must not live longer than this 'a
lifetime or that the value of v
must live at least as long as the Foo
object.
In the call to the method set
, the lifetime parameter on the impl
block is used and the lifetime of the value of w
is filled in for 'a
in the method signature. &mut self
is assigned a different lifetime by the compiler, which is the lifetime of f
(the Foo
object). If I switched the order of the bindings of w
and f
in the main
function, this would result in an error.
I wondered what would happen if I annotated the &mut self
reference with the same lifetime parameter 'a
as r
in the set
method:
impl<'a> Foo<'a> {
fn set(&'a mut self, r: &'a i32) {
self.x = r;
}
}
Which results in the following error:
error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
--> src/main.rs:21:31
|
19 | f.set(&w);
| - mutable borrow occurs here
20 |
21 | println!("now f is {:?}", f);
| ^ immutable borrow occurs here
22 | }
| - mutable borrow ends here
In contrast to the example above, f
is still considered mutably borrowed by the time the second println! is called, so it cannot be borrowed simultaneously as immutable.
How did this come to be?
By not leaving off the lifetime annotation the compiler filled one in for me for &mut self
in the first example. This happens by the rules of lifetime elision. However by explicitly setting it to 'a
in the second example I linked the lifetimes of the value of f
and the value of w
.
Is f
considered borrowed by itself somehow?
And if so, what is the scope of the borrow? Is it min(lifetime of f
, lifetime of w
) -> lifetime of f
?
I assume I haven't fully understood the &mut self
reference in the function call yet. I mean, the function returns, but f
is still considered to be borrowed.
I am trying to fully understand lifetimes. I am primarily looking for corrective feedback on my understanding of the concepts. I am grateful for every bit of advice and further clarification.