&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) {}
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).
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.