Cached at:
06/29/26, 06:30 PM
# What is `std::pin::Pin` in Rust?
Source: [https://vrong.me/blog/what-is-pinning-in-rust/](https://vrong.me/blog/what-is-pinning-in-rust/)
`std::pin::Pin`is a pointer wrapper that represents the guarantee that the pointee will not be moved through that pointer\.
## Why is it required?
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:
```
1struct SelfRef {
2 data: i32,
3 ptr: *const i32, // points to self.data
4}
```
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 prevent moving`SelfRef`once those self\-references have been established\.
### Where do we see this problem?
We see this most commonly with`async`/`await`and`Futures`\.
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\.
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:
```
1pub trait Future {
2 type Output;
3 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
4}
```
By taking`Pin<&mut Self\>`instead of`&mut self`, callers of`poll`are required to guarantee that the future will not be moved after polling begins\.
## How does pinning work?
`Pin<P\>`prevents safe code from moving the pointee through that pointer while still allowing ordinary mutation of the pinned value\.
### The Problem with`&mut T`
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\.
`Pin`restricts recovering an ordinary mutable reference\. Safe code cannot recover an ordinary`&mut T`from a`Pin<&mut T\>`unless`T: Unpin`\.
```
1impl<'a, T: ?Sized> Pin<&'a T> {
2 pub const fn get_ref(self) -> &'a T { ... }
3}
4
5impl<'a, T: ?Sized> Pin<&'a mut T> {
6 pub const fn get_mut(self) -> &'a mut T
7 where
8 T: Unpin
9 { ... }
10}
```
Important
`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\.
### What is`Unpin`?
A type implementing`Unpin`does not rely on pinning for soundness\.
```
1// std::marker
2pub auto trait Unpin {}
```
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\.
Tip
The marker struct`std::marker::PhantomPinned`is explicitly`\!Unpin`\. Because auto\-traits propagate automatically, any struct containing a`PhantomPinned`field is also automatically`\!Unpin`\.
```
1use std::marker::PhantomPinned;
2
3struct SelfRef {
4 data: i32,
5 ptr: *const i32,
6 _phantom: PhantomPinned, // makes the entire struct !Unpin
7}
```
This is the standard way to declare that a custom struct is unsafe to move after being pinned\.
Because the compiler cannot automatically detect self\-references \(which are typically created using unsafe raw pointers\), it cannot automatically mark such structs as`\!Unpin`\.
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\.
`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\.
## Constructing a`Pin`
`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\.
### `Pin::new`
The simplest way to construct a Pin is with`Pin::new`:
```
1let mut value = 42;
2let pinned = Pin::new(&mut value);
```
However, this constructor is only available when`T: Unpin`\.
Since`Unpin`types do not rely on pinning for soundness, wrapping them in a`Pin`is always safe\. The pinning guarantee is effectively a no\-op\.
### `pin\!`
When you need to pin a value locally without allocating on the heap, you can use the`pin\!`macro:
```
1use std::pin::pin;
2
3let future = pin!(async {
4 println!("Hello");
5});
```
The macro creates a local variable and returns a`Pin<&mut T\>`referring to it\. The compiler ensures that the local variable will not be moved for the remainder of its lifetime, making this a safe way to pin`\!Unpin`values on the stack\.
Warning
Despite the name,`pin\!`does not pin the stack memory itself\. It creates a pinned reference whose lifetime is tied to the local variable\. Once the variable goes out of scope, the pinning guarantee ends\.
### `Box::pin`
For`\!Unpin`types, the most common constructor is`Box::pin`:
```
1let pinned = Box::pin(SelfRef { ... });
```
Unlike`pin\!`, which creates a`Pin<&mut T\>`tied to a local variable,`Box::pin`returns a`Pin<Box<T\>\>`whose lifetime is owned by the`Box`\. Because the heap allocation itself does not move, the pointee has a stable memory location for the lifetime of the`Box`, allowing it to be safely pinned\.
Note
Moving the`Box`itself does not move the value it owns\. Only the pointer stored inside the`Box`is moved; the heap allocation remains at the same address\.
### `Pin::new\_unchecked`
Sometimes safe constructors cannot prove that a value will remain in place\. In these cases, unsafe code can construct a`Pin`manually:
```
1let pinned = unsafe { Pin::new_unchecked(ptr) };
```
By calling`Pin::new\_unchecked`, the caller promises that the pointee will never again be moved through any pointer for the lifetime of the resulting`Pin`\. If this promise is violated, any code relying on the pinning guarantee may exhibit undefined behavior\. Because of this,`Pin::new\_unchecked`is typically used only when implementing low\-level abstractions that can uphold this invariant\.
## When do you actually need to care?
For most Rust developers,`Pin`and`Unpin`operate quietly in the background\. You generally only need to think about them in two scenarios:
1. **Consuming async code:**If you need to manually poll a future or pass a future to an API that requires a pinned future, reach for`Box::pin\(future\)`\(to pin it on the heap\) or`std::pin::pin\!\(future\)`\(to pin it locally on the stack\)\.
2. **Implementing`Future`by hand:**If you’re writing a custom state machine or another low\-level async primitive, you’ll need to work with`Pin<&mut Self\>`and may need to use`PhantomPinned`and unsafe code to uphold pinning invariants\.
Ultimately,`Pin`is Rust’s zero\-cost solution to the problem of address\-sensitive types\. It enables ergonomic`async`/`await`and other self\-referential abstractions while preserving Rust’s memory safety guarantees without requiring a garbage collector\.