Why does Pin prevent mem::swap? Does swapping change the memory location of objects?

539 Views Asked by At

I feel confused reading the Pin chapter in Futures Explained in 200 Lines of Rust.

I understand that moving a value breaks self-referential structs:

self-referential struct memory diagram

pin. In Rust, pin is a property that…

The memory location of the struct changed and the self reference pointer will fail to work.

With mem::swap, there is no memory relocation of the struct, only the pointer changed:

#[derive(Debug)]
struct Test {
    a: String,
    b: *const String,
}

before and after swap

Futures Explained in 200 Lines of Rust

The memory location of the struct has not changed.

Another example:

#[derive(Debug)]
struct A {
    a: String,
    b: String,
}

fn main() {
    let mut v1 = A {
        a: String::from("a"),
        b: String::from("a"),
    };

    let mut v2 = A {
        a: String::from("b"),
        b: String::from("b"),
    };

    println!("v1: {:p} - {:?}", &v1, &v1);
    println!("v1 ab:{:p} - {:p}", &v1.a, &v1.b);
    println!("v1 ab ptr :{:p} - {:p}", v1.a.as_ptr(), v1.b.as_ptr());
    println!("v2: {:p} - {:?}", &v2, &v2);
    println!("v2 ab:{:p} - {:p}", &v2.a, &v2.b);
    println!("v2 ab ptr :{:p} - {:p}", v2.a.as_ptr(), v2.b.as_ptr());

    std::mem::swap(&mut v1, &mut v2);
    println!("================");

    println!("v1: {:p} - {:?}", &v1, &v1);
    println!("v1 ab:{:p} - {:p}", &v1.a, &v1.b);
    println!("v1 ab ptr :{:p} - {:p}", v1.a.as_ptr(), v1.b.as_ptr());
    println!("v2: {:p} - {:?}", &v2, &v2);
    println!("v2 ab:{:p} - {:p}", &v2.a, &v2.b);
    println!("v2 ab ptr :{:p} - {:p}", v2.a.as_ptr(), v2.b.as_ptr());
}

The output is:

v1: 0x7ffe13256de0 - A { a: "a", b: "a" }
v1 ab:0x7ffe13256de0 - 0x7ffe13256df8
v1 ab ptr :0x5640172c0b40 - 0x5640172c0b60
v2: 0x7ffe13256e40 - A { a: "b", b: "b" }
v2 ab:0x7ffe13256e40 - 0x7ffe13256e58
v2 ab ptr :0x5640172c0b80 - 0x5640172c0ba0
================
v1: 0x7ffe13256de0 - A { a: "b", b: "b" }
v1 ab:0x7ffe13256de0 - 0x7ffe13256df8
v1 ab ptr :0x5640172c0b80 - 0x5640172c0ba0
v2: 0x7ffe13256e40 - A { a: "a", b: "a" }
v2 ab:0x7ffe13256e40 - 0x7ffe13256e58
v2 ab ptr :0x5640172c0b40 - 0x5640172c0b60

The memory location of v1 v2 stays the same, only the String pointer, the value of a b has swapped.

From the Pin doc:

It is sometimes useful to have objects that are guaranteed not to move, in the sense that their placement in memory does not change, and can thus be relied upon

But swap does not seem to change the memory location. Have I missed some concepts of movement?

Update

I misunderstood the meaning of "move". It's about the value and two pictures are the same thing. Before, I thought that if Test moved, then the address (0x1001) would change, but the address is the variable on the stack, not the value itself.

0

There are 0 best solutions below