Why it is allowed to do something like this:
fn main() {
let mut w = MyStruct;
w.fun1();
}
struct MyStruct;
impl MyStruct {
fn fun1(&mut self) {
self.fun2();
}
fn fun2(&mut self) {
println!("Hello world 2");
}
}
In the above code fun1()
gets mut MyStruct
and calls fun2()
also with mut MyStruct
. Is it double mutable reference in one scope?
This is allowed because the borrow checker can conclude there is only one mutable reference being accessed during execution. While fun2
is running, no other statement in fun1
is being executed. When the next statement in fun1
(if there was any) starts executing, fun2
has already dropped its mutable reference.
In the other question linked:
fn main() {
let mut x1 = String::from("hello");
let r1 = &mut x1;
let r2 = &mut x1;
r1.insert(0, 'w');
}
We can say r2
is never used, but borrow checker decided it shouldn't be allowed. Consider this example:
fn main() {
let mut x1 = String::from("hello");
let r1 = &mut x1;
r1.insert(0, 'w');
let r2 = &mut x1;
r2.insert(0, 'x');
}
This compiles and runs correctly. I suppose borrow checker assumes the lifetime r1
ends before r2
is created. If this makes sense, calling methods that mutate self
shouldn't be so surprising.
(I don't know why the 1st piece of code does not compile, but I am glad rust team made it that way. r2
should not be there anyway.)