Why can we sometimes use `&mut` multiple times in the same scope but sometimes we cannot?

&mut doesn't implement Copy trait, but we can still use that multiple times here, like f1 f2 f3.
This usage is so common that I almost ignore why it is. Could anyone point out for me?

And for f4, which needs a generics parameter, the move semantics come into effect. Now I don't get it...

fn main() {
    {
        let mut a = A;
        let b = &mut a;
        // error: borrow of moved value: `b`
        f4(b);
        f3(b);
        b.f2();
        b.f1();
    }
    {
        let mut a = A;
        let b = &mut a;
        f3(b);
        b.f2();
        b.f1();
        // Works fine
        f4(b);
    }
}

struct A;

impl A {
    fn f1(&mut self) {}
}

trait B {
    fn f2(self)
        where Self: Sized {
    }
}

impl B for &mut A {}

fn f3(_: &mut A) {}
fn f4(_: impl B) {}

playground

1 Like

When you pass a &mut T reference to a function the compiler will automatically "reborrow" it to give the reference a lifetime equal to the function call. If the compiler didn't do this, passing a &mut T reference into a function would move the reference and you would lose access to it.

Think of reborrowing as the compiler automatically rewriting f4(b) to f4(&mut *b).

1 Like

I think you mean f3 instead of f4 here.


Basically the compiler inserts reborrows (and other coercions) before it tries to deduce generic types. For f3, the compiler can see right away that a &mut is being assigned to an &mut, and inserts the reborrow.

For F4, it sees a &mut being assigned to impl B, but it doesn't know what type impl B is yet, so it simply moves the value without any coercions.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.