Skip to main content

Pin

Struct Pin 

1.33.0 · Source
pub struct Pin<Ptr> { /* private fields */ }
Expand description

A pointer which pins its pointee in place.

Pin is a wrapper around some kind of pointer Ptr which makes that pointer “pin” its pointee value in place, thus preventing the value referenced by that pointer from being moved or otherwise invalidated at that place in memory unless it implements Unpin.

See the pin module documentation for a more thorough exploration of pinning.

§Pinning values with Pin<Ptr>

In order to pin a value, we wrap a pointer to that value (of some type Ptr) in a Pin<Ptr>. Pin<Ptr> can wrap any pointer type, forming a promise that the pointee will not be moved or otherwise invalidated. If the pointee value’s type implements Unpin, we are free to disregard these requirements entirely and can wrap any pointer to that value in Pin directly via Pin::new. If the pointee value’s type does not implement Unpin, then Rust will not let us use the Pin::new function directly and we’ll need to construct a Pin-wrapped pointer in one of the more specialized manners discussed below.

We call such a Pin-wrapped pointer a pinning pointer (or pinning ref, or pinning Box, etc.) because its existence is the thing that is pinning the underlying pointee in place: it is the metaphorical “pin” securing the data in place on the pinboard (in memory).

It is important to stress that the thing in the Pin is not the value which we want to pin itself, but rather a pointer to that value! A Pin<Ptr> does not pin the Ptr but rather the pointer’s pointee value.

The most common set of types which require pinning related guarantees for soundness are the compiler-generated state machines that implement Future for the return value of async fns. These compiler-generated Futures may contain self-referential pointers, one of the most common use cases for Pin. More details on this point are provided in the pin module docs, but suffice it to say they require the guarantees provided by pinning to be implemented soundly.

This requirement for the implementation of async fns means that the Future trait requires all calls to poll to use a self: Pin<&mut Self> parameter instead of the usual &mut self. Therefore, when manually polling a future, you will need to pin it first.

You may notice that async fn-sourced Futures are only a small percentage of all Futures that exist, yet we had to modify the signature of poll for all Futures to accommodate them. This is unfortunate, but there is a way that the language attempts to alleviate the extra friction that this API choice incurs: the Unpin trait.

The vast majority of Rust types have no reason to ever care about being pinned. These types implement the Unpin trait, which entirely opts all values of that type out of pinning-related guarantees. For values of these types, pinning a value by pointing to it with a Pin<Ptr> will have no actual effect.

The reason this distinction exists is exactly to allow APIs like Future::poll to take a Pin<Ptr> as an argument for all types while only forcing Future types that actually care about pinning guarantees pay the ergonomics cost. For the majority of Future types that don’t have a reason to care about being pinned and therefore implement Unpin, the Pin<&mut Self> will act exactly like a regular &mut Self, allowing direct access to the underlying value. Only types that don’t implement Unpin will be restricted.

§Pinning a value of a type that implements Unpin

If the type of the value you need to “pin” implements Unpin, you can trivially wrap any pointer to that value in a Pin by calling Pin::new.

use std::pin::Pin;

// Create a value of a type that implements `Unpin`
let mut unpin_future = std::future::ready(5);

// Pin it by creating a pinning mutable reference to it (ready to be `poll`ed!)
let my_pinned_unpin_future: Pin<&mut _> = Pin::new(&mut unpin_future);

§Pinning a value inside a Box

The simplest and most flexible way to pin a value that does not implement