I'm still wondering about how a stored value in a Box is moved. In the following piece of code
struct S {
s: Box<String>,
}
impl S {
fn new() -> Self {
let s = Box::new(String::from("hello"));
println!("s: {:p}", s); // addr: address of s on the heap
Self { s }
}
}
fn main() {
let s0 = S::new();
println!("s0: {:p}", s0.s); // addr0: should be equal to addr?
let s1 = s0;
println!("s1: {:p}", s1.s); // addr1: should be equal to addr0, or not?
}
Running the example, I always got the same address for addr, addr0 and addr1.
I suppose that addr == addr0, but still not sure whether it is guaranteed that addr0 == addr1?
But moreover, we can be certain that no such types exist. A move is a memcpy that cannot possibly change the output of fmt::Pointer::fmt. (well, okay, I guess you could do something silly like have impl Pointer format &self which is of type &&Self, but that's not what I mean...)
I'm pretty sure this is guaranteed, as long as it is observable. As in, as long as you do something like print addresses or compare raw pointers (*const T) through equality, LLVM will suppress optimizations that would invalidate this. (that said, I think it's already extremely conservative with optimizations around heap allocations)
However, beware; the inverse proposition is not true. As in, two pointers are allowed to be equal even if they point to different things in Rust, due to the existence of zero-sized types.