Skip to content

Commit bebbe24

Browse files
fu5haManishearth
authored andcommittedJan 7, 2024
improve Pin struct docs and add examples
1 parent 6818d92 commit bebbe24

File tree

1 file changed

+89
-8
lines changed

1 file changed

+89
-8
lines changed
 

Diff for: ‎library/core/src/pin.rs

+89-8
Original file line numberDiff line numberDiff line change
@@ -900,14 +900,17 @@ use crate::{
900900
/// A pointer which pins its pointee in place.
901901
///
902902
/// [`Pin`] is a wrapper around some kind of pointer `Ptr` which makes that pointer "pin" its
903-
/// pointee value in place, thus preventing the value referenced by that pointer from being moved or
904-
/// otherwise invalidated at that place in memory unless it implements [`Unpin`].
903+
/// pointee value in place, thus preventing the value referenced by that pointer from being moved
904+
/// or otherwise invalidated at that place in memory unless it implements [`Unpin`].
905+
///
906+
/// *See the [`pin` module] documentation for a more thorough exploration of pinning.*
905907
///
906908
/// ## Pinning values with [`Pin<Ptr>`]
907909
///
908910
/// In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a
909911
/// [`Pin<Ptr>`]. [`Pin<Ptr>`] can wrap any pointer type, forming a promise that the **pointee**
910-
/// will not be *moved* or [otherwise invalidated][subtle-details].
912+
/// will not be *moved* or [otherwise invalidated][subtle-details]. Note that it is impossible
913+
/// to create or misuse a [`Pin<Ptr>`] which can violate this promise without using [`unsafe`].
911914
///
912915
/// We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning ref, or pinning
913916
/// [`Box`], etc.) because its existince is the thing that is pinning the underlying pointee in
@@ -917,13 +920,91 @@ use crate::{
917920
/// itself, but rather a pointer to that value! A [`Pin<Ptr>`] does not pin the `Ptr` but rather
918921
/// the pointer's ***pointee** value*.
919922
///
920-
/// `Pin<P>` is guaranteed to have the same memory layout and ABI as `P`.
923+
/// For the vast majoriy of Rust types, pinning a value of that type will actually have no effect.
924+
/// This is because the vast majority of types implement the [`Unpin`] trait, which entirely opts
925+
/// all values of that type out of pinning-related guarantees. The most common exception
926+
/// to this is the compiler-generated types that implement [`Future`] for the return value
927+
/// of `async fn`s. These compiler-generated [`Future`]s do not implement [`Unpin`] for reasons
928+
/// explained more in the [`pin` module] docs, but suffice it to say they require the guarantees
929+
/// provided by pinning to be implemented soundly.
921930
///
922-
/// *See the [`pin` module] documentation for a more thorough exploration of pinning.*
931+
/// This requirement in the implementation of `async fn`s means that the [`Future`] trait requires
932+
/// any [`Future`] to be pinned in order to call [`poll`] on it. Therefore, when manually polling
933+
/// a future, you will need to pin it first.
934+
///
935+
/// ### Pinning a value inside a [`Box`]
936+
///
937+
/// The simplest and most flexible way to pin a value is to put that value inside a [`Box`] and
938+
/// then turn that [`Box`] into a "pinning [`Box`]" by wrapping it in a [`Pin`].
939+
/// You can do both of these in a single step using [`Box::pin`]. Let's see an example of using
940+
/// this flow to pin a [`Future`] returned from calling an `async fn`, a common use case
941+
/// as described above.
942+
///
943+
/// ```
944+
/// use std::pin::Pin;
945+
///
946+
/// async fn add_one(x: u32) -> u32 {
947+
/// x + 1
948+
/// }
949+
///
950+
/// // Call the async function to get a future back
951+
/// let fut = add_one(42);
952+
///
953+
/// // Pin the future inside a pinning box
954+
/// let pinned_fut: Pin<Box<_>> = Box::pin(fut);
955+
/// ```
956+
///
957+
/// If you have a value which is already boxed, for example a [`Box<dyn Future>`][Box], you can pin
958+
/// that value in-place at its current memory address using [`Box::into_pin`].
959+
///
960+
/// ```
961+
/// use std::pin::Pin;
962+
/// use std::future::Future;
963+
///
964+
/// async fn add_one(x: u32) -> u32 {
965+
/// x + 1
966+
/// }
967+
///
968+
/// fn boxed_add_one(x: u32) -> Box<dyn Future<Output = u32>> {
969+
/// Box::new(add_one(x))
970+
/// }
971+
///
972+
/// let boxed_fut = boxed_add_one(42);
973+
///
974+
/// // Pin the future inside the existing box
975+
/// let pinned_fut: Pin<Box<_>> = Box::into_pin(boxed_fut);
976+
/// ```
977+
///
978+
/// There are similar pinning methods offered on the other standard library smart pointer types
979+
/// as well, like [`Rc`] and [`Arc`].
980+
///
981+
/// ### Pinning a value on the stack using [`pin!`]
982+
///
983+
/// There are some situations where it is desirable or even required (for example, in a `#[no_std]`
984+
/// context where you don't have access to the standard library or allocation in general) to
985+
/// pin a value to its location on the stack. Doing so is possible using the [`pin!`] macro. See
986+
/// its documentation for more.
987+
///
988+
/// ## Layout and ABI
989+
///
990+
/// [`Pin<Ptr>`] is guaranteed to have the same memory layout and ABI[^noalias] as `Ptr`.
991+
///
992+
/// [^noalias]: There is a bit of nuance here that is still being decided about whether the
993+
/// aliasing semantics of `Pin<&mut T>` should be different than `&mut T`, but this is true as of
994+
/// today.
923995
///
924-
/// [`pin` module]: self
925-
/// [`Box`]: ../../std/boxed/struct.Box.html
926-
/// [subtle-details]: self#subtle-details-and-the-drop-guarantee
996+
/// [`pin!`]: crate::pin::pin "pin!"
997+
/// [`Future`]: crate::future::Future "Future"
998+
/// [`poll`]: crate::future::Future::poll "Future::poll"
999+
/// [`pin` module]: self "pin module"
1000+
/// [`Rc`]: ../../std/rc/struct.Rc.html "Rc"
1001+
/// [`Arc`]: ../../std/sync/struct.Arc.html "Arc"
1002+
/// [Box]: ../../std/boxed/struct.Box.html "Box"
1003+
/// [`Box`]: ../../std/boxed/struct.Box.html "Box"
1004+
/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin "Box::pin"
1005+
/// [`Box::into_pin`]: ../../std/boxed/struct.Box.html#method.into_pin "Box::into_pin"
1006+
/// [subtle-details]: self#subtle-details-and-the-drop-guarantee "pin subtle details"
1007+
/// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe"
9271008
//
9281009
// Note: the `Clone` derive below causes unsoundness as it's possible to implement
9291010
// `Clone` for mutable references.

0 commit comments

Comments
 (0)