I can't seem to figure out why:
let a = Box::new(5i32);
let _:() = *a;
tells me that the assigned type on the second line is i32
and not &i32
since Deref.deref()
(which I assume is being called at *a
), returns &T
.
Also, if I were to call deref()
myself:
let _:() = <Box<i32> as Deref>::deref(&a);
I get the expected &i32
.
Dereferencing doesn't necessarily produce an (intermediate) value. Consider
The method
i32::clone()
is called with a&self
argument where the reference points to the value inside the box, not to a temporary value that could be produced by(*b)
.The trait
Deref
is part of implementing dereferencing (just likeDerefMut
).There is no corresponding trait to what
*
can additionally do on a box: Move the inner value out and discard the box; this is colloquially calledDerefMove
but remains a compiler-hardcoded box speciality at this point.When the compiler sees
(*a)
, it has to infer whether to useDeref
,DerefMut
or “DerefMove
”; it is inferred from how the expression is used: if you call a&self
method on the result,Deref
is used, for example.Edited: Inherently copyable types (trait
Copy
), useDeref
followed by copy instead of “DerefMove
”; this is then no longer resticted to Box, but works with all smart pointers.*foo
is not the same as callingfoo.deref()
. If it were, you'd never be able to actually dereference a value. ^_^*
is syntactic sugar for "callDeref::deref
and then go into the address provided". This is just what people expect from that operator.Deref
exists to make it extensible.That last bit glosses over some details that bluss' answer covers much better.