*Box<T> vs *(Box<T>.deref())


use std::ops::Deref;
fn main() {
    let box_people = Box::new(People {
        name: String::from("test"),
    });
    let _p = *box_people; // move the ownership of box_people to p
    
    let box_people = Box::new(People {
        name: String::from("test"),
    });
    // let _p = *(box_people.deref()); // cannot compile
    
}
#[derive(Debug)]
struct People {
        name: String,
    }

(Playground)

Hi guys,
in the book, the rust compile will operate *Box<T> as *(Box<T>.deref()).
I have checked the deref method actually only provides the borrow of T, which means if T without Copy trait cannot move the ownership of shared reference. So if let _p = *box_people is equal to let _p=*(box_people.deref()), it will not make sense to Rust's borrow check. In fact, rust compiler throw a error, when I try let _p=*(box_people.deref()). So now I don't understand why let _p = *box_people can work and the data in box is also moved out to a new variable.

1 Like

No, as a special case, this is not true for a couple of types, including Box. Dereferencing Boxes (and also regular references) doesn't go through the Deref impl.

5 Likes

Thank you so much for your reply. I am curious about how to gain a better understanding of this inner mechanism. If it's not too much trouble, could you provide me with a guide? Your help is greatly appreciated.

I'm not sure what the "inner mechanism" is that you are referring to.

If you mean ways in which Box is special,

  • Deref and DerefMut are built-in operations and recognized to be "pure"
    • So you can e.g. split field borrows of a &mut Box<SomeType> like you can a &mut SomeType
  • The compiler understands Box indicates unique ownership too
    • Which allows *some_box to move items out of the box
    • And has some aliasing implications you probably need not think about
  • It is "fundamental" for coherence, like references are
    • So you can implement for Box<YourType> like you can for YourType
    • Including Box<dyn YourTrait>

And less special on nightly

  • It's a receiver type (self: Box<Self>)
  • You can unsize the contents of a Box
2 Likes

I apologize for not being clear earlier. My question is how can I gain insight into the internal workings of the Rust compiler for the special case you mentioned.

You don't need to know the internals of the compiler. This behavior of Box is documented.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.