This question already has an answer here:
Here is a sample:
struct X(u32);
impl X {
fn f(&mut self, v: u32) {}
}
fn main() {
let mut x = X(42);
// works
let v = x.0;
x.f(v);
// cannot use `x.0` because it was mutably borrowed
x.f(x.0);
}
error[E0503]: cannot use `x.0` because it was mutably borrowed
--> src/main.rs:16:9
|
16 | x.f(x.0);
| - ^^^ use of borrowed `x`
| |
| borrow of `x` occurs here
What is the reason why x.f(x.0)
does not work? x.0
is passed as an argument, bound to the v
parameter, of type u32
: there is absolutely no possibility that the function body access x.0
through the parameter.
Moreover, it seems very weird to me that:
f(something);
doesn't work, while:
v = something;
f(v);
works.
When you do
x.f(x.0)
, you have borrowedx
to provide the&mut self
tof
before trying to borrowx
again to get a reference tox.0
. It is not possible to refer tox.0
twice at the same time. That is, the methodf
can't have both mutable access tox
via&mut self
(which includesx.0
) and a seemingly immutable reference tox.0
at the same time.When using a temporary variable, you actually get a copy of the value; this means you no longer
refer to that int in X
but42
. That's allowed.Regarding the "non-lexical lifetimes" comments: Since
f
takes a good old u32 instead of a reference to it,x.f(x.0)
should basically be equivalent tox.f(42)
, because the compiler can let go ofx
after getting the value out ofx.0
and then mut-borrowx
again to provide&mut self
tof
. However, the compiler determines the lifetimes and their requirements very early on during compilation; lifetimes are therefor currently broader than they have to be.rustc
is currently unable to determine that the borrow onx
due to thex.0
argument has ended before borrowingx
for&mut self
. There is work underway to fix this.