Dynamic – ownership tracking in rust: difference between box (heap) and t (stack)
Trying to use the programming language rust, I found that the compiler can track the movement of some structural fields in the stack very accurately (it knows exactly which field has been moved)
struct OuterContainer { inner: InnerContainer } struct InnerContainer { val_a: ValContainer,val_b: ValContainer } struct ValContainer { i: i32 } fn main() { // Note that the whole structure lives on the stack. let structure = OuterContainer { inner: InnerContainer { val_a: ValContainer { i: 42 },val_b: ValContainer { i: 100 } } }; // Move just one field (val_a) of the inner container. let move_me = structure.inner.val_a; // We can still borrow the other field (val_b). let borrow_me = &structure.inner.val_b; }
Now it's the same example, but there's only one small change: we put innercontainer into a box (@ r_997_2419 @ < innercontainer >)
struct OuterContainer { inner: @R_997_2419@<InnerContainer> } struct InnerContainer { val_a: ValContainer,val_b: ValContainer } struct ValContainer { i: i32 } fn main() { // Note that the whole structure lives on the stack. let structure = OuterContainer { inner: @R_997_2419@::new(InnerContainer { val_a: ValContainer { i: 42 },val_b: ValContainer { i: 100 } }) }; // Move just one field (val_a) of the inner container. // Note that Now,the inner container lives on the heap. let move_me = structure.inner.val_a; // We can no longer borrow the other field (val_b). let borrow_me = &structure.inner.val_b; // error: "value used after move" }
I suspect it has something to do with the nature of the stack, which is static (at least every stack frame), and the nature of the heap, which is dynamic Maybe the compiler needs to use it safely because I can't express / recognize it clearly
Solution
In the summary, the structure on the stack is just a pile of variables under a common name The compiler knows this and can decompose the structure into a set of independent stack variables This allows it to track the movement of each field independently
It can't use @ R_ 997_ 2419 @ or any other type of custom assignment because the compiler does not control @ R_ 997_ 2419@. @R_ 997_ 2419 @ is just some code in the standard library, not an inherent part of the language@ R_ 997_ 2419 @ can't infer that different parts of themselves suddenly become invalid When @ r is destroyed_ 997_ 2419 @ its drop implementation only knows to destroy everything
In other words: on the stack, the compiler is in full control, so it can perform strange operations, such as breaking structures and moving them one by one Once the custom assignment enters the picture, all bets will be closed, and the compiler must exit and stop trying to become smart