let mut a = String::from("test");
let b = & mut a;
let c = b; // #1 b is moved here
println!("{b}"); // #2 error
Since & mut T does not implement Copy trait, b is moved to c at #1 and cannot be used at #2, the compiler emit the expected error Rust Playground
However, if we add the type annotation for variable c, the case will become weird
let mut a = String::from("test");
let b = & mut a;
let c: & mut String = b; // #3
println!("{b}"); // #4
The use of b at #4 is ok. Rust Playground The only possible reason I supposed is that the reborrow mechanism occurs at #3. Is this the recorded context for reborrowing?
The question seems to be "why reborrow triggered only in second case, not in the first?" The current rule of thumb is simple - "reborrow before inference". That is, all reborrows are inserted when the type is already known; if it has to be inferred - it will be inferred with lifetime and won't be subject to reborrowing rules.
I'm not sure whether reborrowing counts as coercion, however - otherwise it wouldn't help with multiple consecutive mutable borrows, since the original borrow would still be moved (and only then coerced).
But if you still don't buy it as a coercion (and I don't know that I'd disagree), my previous post can be rephrased as "I'm unaware offhand of any reborrow site that's not also a coercion site (and vice-versa)".
(I still haven't taken the time to play around to poke at that hypothesis though.)
One interesting aspect of coercion is its interaction with inference. For coercion rules to make sense, we need to know all the types involved. But in some cases we are in the process of inferring the types, and the decision of whether or not to coerce would in fact affect the results of that inference. In such cases we currently do not coerce.
which agrees with the rule of thumb mentioned by @Cerber-Ursi .
though things like ~T, autoborrowed function arguments and silent mutability don't exist today. âŠī¸