Consider the following code:
let x = String::from("123");
let bx = Box::new(x);
let dbx = *bx;
println!("{}", dbx);
//println!("{}", bx); // error due to ownership move
Here x is created, later boxed into bx, and later bx is somehow unboxed in expression *bx.
As far as I understand, ownership of data is moved from x to bx to dbx, and data itself (at least memory occupied by struct String) is copied from stack (x) to heap (pointed by bx) to stack (dbx).
My main question is: how does compiler interpret *bx?
It does not look like Deref for Box, since this would imply claiming ownersip of value, having reference to value (&String).
It looks like compiler somehow desugars this to into_inner, but it is not obvious to me why.
So, What is going on here?
Bonus question: is there a way to see how code gets desugared, or how do I approach demystifying rust magic in general. Auto dereferencing involving various smart pointers is of particular interest to me now. I tried cargo-inspect but it does not seem to be helpful here.
Normally you are right that
*goes throughDereforDerefMutand only has access to&Tor&mut T. However,Boxgets special treatment and is allowed by the compiler to move out of a dereference.There is currently no trait that allows one to do that for user-defined types (a
DerefMovetrait has been proposed but nothing accepted AFAIK). So there is no "desugaring" to be done; just*bxis what you see and what is left is handled by the compiler internally. It really is "magic" in this case.You can see that it doesn't desugar to
into_innerbecause the current implementation of that is to use*(source):See also: