How is Boxed value moved

#1

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?

Many thanks for any response.

#2

Moving a Box doesn’t move what the Box points to. fmt::Pointer formatting prints the address of what is stored in the Box.

4 Likes
#3

Also even for types that do change address when moved, the optimizer is free to optimize the move out.

#4

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.

1 Like
#5

I’ve meant this:

fn main() {
    struct Foo(u8);
    let foo = Foo(1);
    println!("{:p}", &foo);
    let bar = foo;
    println!("{:p}", &bar);
}

It seems that printing the address forces the compiler to have a unique one, but moves that aren’t observed are optimized out:

1 Like