Why pinning exists
Most Rust values are freely movable — taking ownership copies the bytes to a new location. But self-referential structs (a struct that holds a pointer into its own body) become invalid the moment they move. Async functions generate self-referential structs internally to track suspended state. `Pin<P>` is the smart-pointer wrapper that statically prevents the pointee from being moved out, making such patterns sound.
Pin and Unpin
`Unpin` is the marker that says "this type doesn't care about pinning — moving it is always fine". Almost every type is Unpin automatically. The exceptions — async futures, intrusive data structures — are `!Unpin`, and only those types get any benefit from `Pin`. For `T: Unpin`, `Pin<&mut T>` and `&mut T` are equivalent.
For deeper background, see a complete cheat-sheet of std collection complexities for the broader context behind this section.
Constructing a Pin
`Pin::new` works for `T: Unpin` and is essentially a no-op. For `!Unpin` types, you typically obtain a `Pin` via `Box::pin(value)` (heap pinning) or the `pin!(...)` macro (stack pinning, stable since 1.68). Once a value is pinned you can no longer move it, except via the unsafe `get_unchecked_mut`.
Pin in Future::poll
Every `Future::poll` takes `Pin<&mut Self>`. That's how the runtime promises the future's memory will not move while it's suspended — required for the compiler-generated async state machines that may hold references into their own locals.
For deeper background, see the official Rust API guidelines for module-level design for the broader context behind this section.
When you actually need to think about Pin
Almost never, in application code. Use `async fn` and `await`; let the compiler manage pinning. Pin only enters your day-to-day vocabulary if you build a runtime, write a custom Future implementation by hand, or implement an intrusive data structure for performance reasons.