What is `std::pin::Pin` in Rust? | vrongmealWhat is std::pin::Pin in Rust?<br>29 Jun 2026<br>std::pin::Pin is a pointer wrapper that represents the guarantee that the pointee will not be moved through that pointer.<br>Why is it required?<br>The need for pinning arises from self-referential types. Self-referential structs are the most common example of address-sensitive types, and are the primary motivation for Pin. Take the following struct for example:<br>1struct SelfRef {<br>2 data: i32,<br>3 ptr: *const i32, // points to self.data<br>4}<br>If we move an instance of this struct (for example, by moving ownership into another variable or returning it), its memory address changes. However, the raw pointer ptr still refers to the old memory location, leaving a dangling pointer. Hence, we need a way to mark SelfRef as unsafe to move once those self-references have been established, so any API that touches it must respect that. Rust cannot physically prevent moves. Instead, Pin encodes this as a type-level guarantee, which the rest of this post unpacks.<br>Where do we see this problem?<br>We see this most commonly with async/await and Futures.<br>Local variables that live across an .await point become fields in the compiler-generated state machine. If a reference to one local variable also lives across the same .await, the generated future becomes self-referential.<br>Once polling begins, the future may rely on internal references that point to other fields within itself. Moving the future afterward would invalidate those references. To prevent this, the Future::poll method requires the future to be pinned:<br>1pub trait Future {<br>2 type Output;<br>3 fn poll(self: Pinmut Self>, cx: &mut Context'_>) -> PollSelf::Output>;<br>4}<br>By taking Pin instead of &mut self, callers of poll are required to guarantee that the future will not be moved after polling begins.<br>How does pinning work?<br>Pin prevents safe code from moving the pointee through that pointer while still allowing ordinary mutation of the pinned value.<br>The Problem with &mut T<br>If you have a mutable reference &mut T, functions like mem::replace, mem::swap, or assignment can relocate the value stored at that memory location.<br>Pin restricts recovering an ordinary mutable reference. Safe code cannot recover an ordinary &mut T from a Pin unless T: Unpin.<br>1impl'a, T: ?Sized> Pin'a T> {<br>2 pub const fn get_ref(self) -> &'a T { ... }<br>3}<br>5impl'a, T: ?Sized> Pin'a mut T> {<br>6 pub const fn get_mut(self) -> &'a mut T<br>7 where<br>8 T: Unpin<br>9 { ... }<br>10}<br>Important<br>Pin only prevents moves through the pinned pointer. It does not prevent mutation of the pinned value. Methods on the pinned type may freely mutate its fields, provided they do not move them.
If the type does not implement Unpin (i.e., it is !Unpin), you cannot get &mut T using safe code. You must use unsafe methods like Pin::get_unchecked_mut, indicating to the compiler that you promise not to move the value out of that reference.<br>What is Unpin?<br>A type implementing Unpin does not rely on pinning for soundness.<br>1// std::marker<br>2pub auto trait Unpin {}<br>Most types in Rust (like i32, String, Vec, etc.) do not care about being moved and are Unpin by default. Unpin is implemented for all types automatically unless !Unpin is explicitly implemented.<br>Tip<br>The marker struct std::marker::PhantomPinned is explicitly !Unpin. Because auto-traits propagate automatically, any struct containing a PhantomPinned field is also automatically !Unpin.<br>1use std::marker::PhantomPinned;<br>3struct SelfRef {<br>4 data: i32,<br>5 ptr: *const i32,<br>6 _phantom: PhantomPinned, // makes the entire struct !Unpin<br>7}<br>This is the standard way to declare that a custom struct is unsafe to move after being pinned. On stable Rust, it is also the only way: writing impl !Unpin for MyType {} directly requires the negative_impls feature, which is only available on nightly. PhantomPinned exists as a public marker so that opting out of Unpin is possible on stable.
Because the compiler cannot automatically detect self-references (which are typically created using unsafe raw pointers), it cannot automatically mark such structs as !Unpin.<br>Therefore, this relies on a contract: the developer must explicitly opt out of Unpin (typically by embedding a PhantomPinned field) for any self-referential struct. If a self-referential type mistakenly remains Unpin, safe code can recover a mutable reference from a Pin and move the value, violating the assumptions made by the unsafe code that created the self-reference.<br>Pin does not physically prevent values from moving. Instead, it is a type-level guarantee that the value will not be moved through that pointer. Constructing a Pin safely therefore requires ensuring that the pointee will remain at a stable memory location for the lifetime of that pin.<br>Constructing a Pin<br>Pin itself does not pin a value. Instead, constructing a Pin means proving that the pointee will remain at a stable memory location for the lifetime of that pin.<br>Pin::new<br>The simplest way to construct a Pin is with...