So... what is Pin anyway?

It's for self-referential data-structures. Let's try making one. Here we have a struct pointing to itself.


    struct MyStruct<'a> {
        x: String,
        y: &'a String,
    }

    let s = String::new();
        - move occurs because `s` has type `String`, which does not implement the `Copy` trait
    
    let my_struct = MyStruct { x: s, y: &s };
                                  -     ^^ value borrowed here after move
                                  |
                                  value moved here
    

Hmmm, s is moved after we take a reference to it. Let's try.


    struct MyStruct<'a> {
        x: String,
        y: Option<&'a String>,
    }

    let s = String::new();
    let mut my_struct = MyStruct { x: s, y: None };

    my_struct.y = Some(&my_struct.x);
    

It compiles! But as soon as we try to do anything with it, even something as innoculous as calling drop...

error[E0505]: cannot move out of `my_struct` because it is borrowed
    drop(my_struct)
         ^^^^^^^^^
         |
         move out of `my_struct` occurs here
    

Why is this a problem? Why won't Rust just let me do it?

Most compile errors in Rust hint at some bigger issue in your program. Let's see what our struct looks like in memory.


        .-------------.
        v             |
    .-----------.------------.
    | x: String | y: &String |
    .-----------.------------.
    

If we try to call drop, we move the value to a new location in memory and free the old space.


        .---------------------------------------------.
        v                                             |
    .------------------------.      .-----------.------------.
    |         freed          |      | x: String | y: &String |
    .------------------------.      .-----------.------------.
    

But look! When Rust moves a value, it does so bit by bit, copying the data exactly. Our pointer now points to the old location which is now empty! That's UB!

Let's say I'm writing a library, and I have a self-referential struct that uses unsafe raw pointers.


    struct MyStruct {
        x: String,
        y: *const String,
    }
    

This is a problem, if I give my users an &mut MyStruct then they can use std::mem::* functions to move the struct around and cause UB. In Rust, it is true that if you give someone an &mut pointer, they can use it to move the data. How do I give my users MyStruct without letting them move it?

This is where Pin comes in. Pin isn't a special compiler feature. It's actually just a regular struct, and it looks like this.


    pub struct Pin<Ptr> {
        pointer: Ptr,
    }
    

Yup! That's it!

Instead of giving my users an &mut MyStruct. I can give them a Pin<&mut MyStruct>. If they try to std::mem::take it, they'll get an error!


    fn do_bad_stuff(my_struct: Pin<&mut MyStruct>) {
        std::mem::take(my_struct);
        -------------- ^ expected `&mut _`, found `Pin<&mut MyStruct>`
        |
        arguments to this function are incorrect
    }
    

In short, Pin guarantees that the value behind a reference will never move.

You can pin a value on the heap with Box::pin. You can pin a value on the stack with the pin! macro. Or if the type implements Unpin you can just use Pin::new. Unpin is an escape hatch that says "hey I know I wrapped this type in a Pin<T> but just disregard that because I actually don't care if you move it.". It's used to call functions that expect a Pin<T> even when pinning T has no effect.

and why does Future need it?

Futures are state-machines. Let's look at an example.


    async fn crunch_numbers() {
        let x = 1;
        println!("Om! {x}");
        let y = 2
        let z = &y;
        println!("Nom! {z}");
    }
    

Rust turns this into something like.


    fn crunch_numbers() -> impl Future {
        CrunchNumbersStateMachine::Start
    }

    enum CrunchNumbersStateMachine {
        Start,
        Om { x: i32 },
        // z points to y
        Nom { y: i32, z: *const i32 },
        Done,
    }
    

Do you see that? Yup, it's a self-referential struct.

Let's look at the function signature for Future::poll.


    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
    

The Pin<&mut Self> just means "hey if you're going to poll the future, please don't move it.". You can imagine it would be pretty bad if a future got half-way through execution, with active references into itself, and then suddenly got moved to another place in memory.

Pin might become obsolete in the future.