Search code examples
rustlinked-list

Are there anyways to unbox a Box value besides using the * operator?


Am currently going through the Peek section of the Rust linked list guide: https://rust-unofficial.github.io/too-many-lists/second-peek.html

pub fn peek(&self) -> Option<&T> {
    self.head.as_ref().map(|node| { //node is of type &Box<Node<T>>
        &node.elem
    })
}

It seems that we are able to directly unbox node with the "." operator instead of using the "*" as is traditionally shown in Box tutorials.

Can someone please advise what is happening underneath the hood?


Solution

  • The dot operator is magic: https://doc.rust-lang.org/nomicon/dot-operator.html

    If I am not mistaken, in this code:

    &node.elem
    

    the . operator appears to call the Deref<Target=T> trait of Box, which just returns &**self, where self is your Box<List>

    You could replace the above code in peek() with:

    ((&**node).elem)
    

    The code in the peek() function effectively does the following (though this code won't actually be allowed, unless it's in-line, like the Deref<> or AsRef<> or Borrow<> trait impls do it):

    // let box: &Box<T> = node;    // It's actually this: &Box<Unique<T>> -- T is a struct
    // let node: Unique<T> = box;
    // let inner_struct:  T = node;
    // let member: U = inner_struct.member_name;     // Here you can access members of T struct
    // let ref_to_member: &U = &member;    // This can be returned as borrowed
    

    struct.member => So the . operator "magically" knows to call Deref here. More details on how the rust compiler knows how to do this can be found here: https://rustc-dev-guide.rust-lang.org/method-lookup.html

    Here is more on how Derefs work: https://micouy.github.io/rust-dereferencing/

    Relevant Box code in rust std lib: https://doc.rust-lang.org/src/alloc/boxed.rs.html#2037