The compiler inserts a reborrow in any possible location where a &mut T
is "moved" into a place that already has its type known to be &mut _
(where the _
is anything; it could be T
, it could be some other U
(in which case coercions may also be inserted), or it could even be left up to type inference with _
(in which case it is always inferred to be T
)).
So:
let x = 0;
let y = &mut x;
let z: &mut i32 = y; // This is an implicit reborrow (equiv. to &mut *y)
let z: &mut _ = y; // This is an implicit reborrow
let z: _ = y; // This is a move
let z = y; // This is a move
Similar examples using function calls
fn takes_mut_i32(_arg: &mut i32) {}
fn takes_mut_t<T>(_arg: &mut T) {}
fn takes_any_t<T>(_arg: T) {}
takes_mut_i32(y); // this is an implicit reborrow
takes_mut_t(y); // this is an implicit reborrow
takes_any_t(y); // this is a move; sometimes this surprises people and there
// have been countless "bugs" filed about it