0
votes

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?

1
Also, main calls w.fun1() and still has w in its scope… - Bergi
Yeap, I don't understand why it works. For example this is not allowed: stackoverflow.com/q/58364807/9620900 - mikeProgrammer
I have read rust-book section about borrowing and references many times. I didn't find answer for my question there. - mikeProgrammer
No, they are not in the same scope. Sure, they might all exist at the same time, but only one of them is non-borrowed. - Bergi

1 Answers

2
votes

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.)