Confusing ' * ' behavior on smart pointer type?



I am wondering why the rust language choose to automatically call box.deref() when using *box and box is a smart pointer. Because box is actually not a reference (& or &mut).

When glancing through rust code, it often leads to confusion whether I am looking at a typical borrow reference or a smart pointer type.

Is there any plan or way to set the default behavior of *box back to *box.deref()??



I think there is a certain symmetry and it is nice that given the following types of pointers:

  • ptr: &T
  • ptr: Box<T>
  • ptr: Rc<T>
  • ptr: Arc<T>
  • ptr: *const T

they all have one thing in common; the type of the expression *ptr is T. We have a pointer, with a star we have the element it points to.

Now it depends of course on the pointer type what we can actually do through that syntax – if we can borrow, mutate or move or copy the element.



But * only applies to reference or raw pointers right? Since some documents said rust only has two types of pointers, reference and raw pointers.

ptr: &T
ptr: Box ===>>> NOT Pointer in compiler’s view
ptr: Rc ===>>> NOT Pointer in compiler’s view
ptr: Arc ===>>> NOT Pointer in compiler’s view
ptr: *const T

I think *box.deref() is better in a sense that it makes very clear where the pointer comes from. Saving a few keystrokes but add quite complexity to make code not that readable and make the concept harder to understand. the trait name deref is also misleading since it actually gives a reference back…


No, it applies to types implementing Deref.


My point here is then * should not apply to Deref.


That is literally the entire reason for Deref to exist.


Well, shouldn’t smart pointer different from reference and raw pointers? since they own their data and allocate on heap and have extra meta information? And probably internal implementation is very different from others?

a Deref or DerefMut or DerefMove are all much better than use deference * syntax.

mangling the inherently different concepts together is really confusing.


As I see it all those types mean an indirection to the T value, in contrast to a raw T that is directly embedded in the parent structure or on the stack. And the deference syntax (*) means to follow that indirection.

The entire point of Deref and friends is to make this possible and to make smart pointers feel like raw pointers / references.


This might be a reach, but I’d wager that every single Deref impl in the standard library boils down to “return the pointer stored at (constant field offset)”.

EDIT: Ooookay. I just learned that you can apparently move out of a Box by dereferencing it, which is an absurdly niche hack to have in the language only for everybody’s “favorite heap allocation type that nobody uses”.