Pin wrapper doesn't work?

I'm running the following in Rust Playground:

use std::pin::Pin;

fn main() {
    let x = 5;
    let y = Pin::new(&x);
    let z = x;
    
    println!("x: {}", x);
    println!("y: {}", y);
    println!("z: {}", z);
}

Based on what I've read, pinning is supposed to prevent x from being moved. And yet, I'm successfully moving it in the above code without compiler errors, as if the Pin wrapper didn't exist. What am I doing wrong?

Well, there are two things to correct here.

First: this line let z = x; doesn't move x, it copies it. x is of type i32 which implements the Copy trait. if you try the same code with a type that isn't Copy, such as String (or just Box the i32) it won't compile.

Second: that's not how Pin works. Pin prevents a value from moving in memory, here are the docs for pinning: std::pin - Rust

1 Like

To add to @jvcmarcenes's answer, x's type is i32. i32 implements the Unpin trait, which "cancels" the effect of Pin and thus allowing your type to be unpinned.

Pin does not magically make your values pinned. In fact Pin::new is only callable with types that implement Unpin, on which Pin has no effect at all. Pin is just a way for an API to require pinned values (if they require themself to be pinned). An example is Future. The job to guarantee that the value remains pinned is for the user, which must guarantee it manually with the unsafe Pin::new_unchecked or use something that wraps it, for example the std::pin::pin/futures::pin_mut! macros or Box::pin.

4 Likes

Nope, that's not how Pin works. What made you think that Pin would magically make a totally normal i32 unrelated x unmoveable?

Probably not reading the documentation carefully enough? Specifically that part: It is worth reiterating that Pin<P> does not change the fact that a Rust compiler considers all types movable. mem::swap remains callable for any T . Instead, Pin<P> prevents certain values (pointed to by pointers wrapped in Pin<P> ) from being moved by making it impossible to call methods that require &mut T on them (like mem::swap).

IOW: Pin doesn't prevent the target of the pointer from being moved. Instead it ensures that you cannot get a pointer from Pin to use it directly! And if you cannot do that then, of course, you cannot move objects in that case.

1 Like

I think you were rather quick to assume that I haven't read the documentation carefully enough. I actually have been reading lots of documentation lately, but sometimes it's hard to know which interpretation is correct and how the theory looks like more concretely in actual code, and that's why I'm using this forum to clear out any ambiguities.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.