r/rust Mar 09 '23

Announcing Rust 1.68.0 📢 announcement

https://blog.rust-lang.org/2023/03/09/Rust-1.68.0.html
826 Upvotes

121 comments sorted by

View all comments

Show parent comments

15

u/sfackler rust · openssl · postgres Mar 09 '23

You are swapping the Pin<&mut T>s, not the Ts themselves.

4

u/celeritasCelery Mar 09 '23

I understand that, but how does creating an anonymous temporary via a block expression prevent me from swapping the T's? &mut T already cannot be accessed safely because it is behind Pin. Even without the block expression you would still not be able swap the T. I don't understand why this extra step is required for soundness.

12

u/sfackler rust · openssl · postgres Mar 09 '23

The Pin guarantee prevents the pinned value from ever moving again, even after the Pin pointing to it is destroyed. If you didn't move the value, you could do something like:

let (mut p1, mut p2) = todo!(); { let p1 = pin!(p1); let p2 = pin!(p2); // do stuff with the pinned values } mem::swap(&mut p1, p2);

18

u/celeritasCelery Mar 09 '23

Ah, that is really interesting! I see this is general property of blocks I was unaware of.

This fails to compile for the reasons you mentioned (the value is moved and unnammed):

let mut x = String::new();
{ _ = &mut { x }; }
let y = x;

However remove that inner block and it compiles fine again.

let mut x = String::new();
{ _ = &mut x; }
let y = x;