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:
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,
}
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.