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.