How to make sense of the following piece of code? I'm new to Rust but have background on C/Haskell and a little bit C++. The only reference I can find is to deref coercions.
fn main() {
let xs: [u32; 4] = [0, 1, 2, 3];
let mut i: u32 = 0;
for x in xs.iter() {
if i > *x { // It looks x is an iterator. Understood.
i = i + x; // no error. (coerced)
//Quote: "Rust will do this as many times
// as possible until the types match."
i = i + *x; // no error (explicit deref)
i += x; // error about u32/&u32 mismatch. Why the magic failed?
i += *x; // no error (explicit deref)
}
}
println!("{}", i);
}
There is no auto-deref or coercion here,
i + x
works simply becauseu32
implements bothAdd<u32>
andAdd<&u32>
. If you check the docs foru32
, you'll find the following four trait impls:u32
only implementsAddAssign<u32>
but notAddAssign<&u32>
(this is a bug andwill be fixed in 1.18 or 1.19fixing it causes regression which means this impl probably needs to wait for Rust 2.0), soi += x
is an error.Why does auto-dereferencing not happen? — Auto-deref only happens when it is a receiver i.e. the "
self
" in a method callfoo.bar()
.x
is not a "self" argument and+
is not a method call. So there's no auto-deref here. See What are Rust's exact auto-dereferencing rules? for detail.