Skip to content

Commit 721b5fa

Browse files
committed
improve Pin and Pin::new docs
1 parent cd13f5c commit 721b5fa

File tree

1 file changed

+67
-23
lines changed

1 file changed

+67
-23
lines changed

library/core/src/pin.rs

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -946,8 +946,13 @@ use crate::{
946946
///
947947
/// In order to pin a value, we wrap a *pointer to that value* (of some type `Ptr`) in a
948948
/// [`Pin<Ptr>`]. [`Pin<Ptr>`] can wrap any pointer type, forming a promise that the **pointee**
949-
/// will not be *moved* or [otherwise invalidated][subtle-details]. Note that it is impossible
950-
/// to create or misuse a [`Pin<Ptr>`] which can violate this promise without using [`unsafe`].
949+
/// will not be *moved* or [otherwise invalidated][subtle-details]. Note that it is
950+
/// impossible to create or misuse a [`Pin<Ptr>`] to violate this promise without using [`unsafe`].
951+
/// If the pointee value's type implements [`Unpin`], we are free to disregard these requirements
952+
/// entirely and can wrap any pointer to that value in [`Pin`] directly via [`Pin::new`].
953+
/// If the pointee value's type does not implement [`Unpin`], then Rust will not let us use the
954+
/// [`Pin::new`] function directly and we'll need to construct a [`Pin`]-wrapped pointer in one of
955+
/// the more specialized manners discussed below.
951956
///
952957
/// We call such a [`Pin`]-wrapped pointer a **pinning pointer,** (or pinning ref, or pinning
953958
/// [`Box`], etc.) because its existince is the thing that is pinning the underlying pointee in
@@ -957,25 +962,57 @@ use crate::{
957962
/// itself, but rather a pointer to that value! A [`Pin<Ptr>`] does not pin the `Ptr` but rather
958963
/// the pointer's ***pointee** value*.
959964
///
960-
/// For the vast majoriy of Rust types, pinning a value of that type will actually have no effect.
961-
/// This is because the vast majority of types implement the [`Unpin`] trait, which entirely opts
962-
/// all values of that type out of pinning-related guarantees. The most common exception
963-
/// to this is the compiler-generated types that implement [`Future`] for the return value
964-
/// of `async fn`s. These compiler-generated [`Future`]s do not implement [`Unpin`] for reasons
965-
/// explained more in the [`pin` module] docs, but suffice it to say they require the guarantees
966-
/// provided by pinning to be implemented soundly.
965+
/// The most common set of types which require pinning related guarantees for soundness are the
966+
/// state machines that implement [`Future`] for the return value of `async fn`s under the
967+
/// hood. These compiler-generated [`Future`]s may contain self-referrential pointers, one of the
968+
/// most common use cases for [`Pin`]. More details on this point are provided in the
969+
/// [`pin` module] docs, but suffice it to say they require the guarantees provided by pinning to
970+
/// be implemented soundly.
967971
///
968-
/// This requirement in the implementation of `async fn`s means that the [`Future`] trait requires
969-
/// any [`Future`] to be pinned in order to call [`poll`] on it. Therefore, when manually polling
970-
/// a future, you will need to pin it first.
972+
/// This requirement from the implementation of `async fn`s means that the [`Future`] trait
973+
/// requires all calls to [`poll`] to use a <code>self: [Pin]\<&mut Self></code> parameter instead
974+
/// of the usual `&mut self`. Therefore, when manually polling a future, you will need to pin it
975+
/// first.
976+
///
977+
/// You may notice that `async fn`-generated [`Future`]s are only a small percentage of all
978+
/// [`Future`]s that exist, yet we had to modify the signature of [`poll`] for all [`Future`]s
979+
/// to accommodate them. This is unfortunate, but there is a way that the language attempts to
980+
/// alleviate the extra friction that this API choice incurs: the [`Unpin`] trait.
981+
///
982+
/// The vast majority of Rust types have no reason to ever care about being pinned. These
983+
/// types implement the [`Unpin`] trait, which entirely opts all values of that type out of
984+
/// pinning-related guarantees. For values of these types, pinning a value by pointing to it with a
985+
/// [`Pin<Ptr>`] will have no actual effect.
986+
///
987+
/// The reason this distinction exists is exactly to allow APIs like [`Future::poll`] to take a
988+
/// [`Pin<Ptr>`] as an argument for all types while only forcing [`Future`] types that actually
989+
/// care about pinning guarantees pay the ergonomics cost. For the majority of [`Future`] types
990+
/// that don't have a reason to care about being pinned and therefore implement [`Unpin`], the
991+
/// <code>[Pin]\<&mut Self></code> will act exactly like a regular `&mut Self`, allowing direct
992+
/// access to the underlying value. Only types that *don't* implement [`Unpin`] will be restricted.
993+
///
994+
/// ### Pinning a value of a type that implements [`Unpin`]
995+
///
996+
/// If the type of the value you need to "pin" implements [`Unpin`], you can trivially wrap any
997+
/// pointer to that value in a [`Pin`] by calling [`Pin::new`].
998+
///
999+
/// ```
1000+
/// use std::pin::Pin;
1001+
///
1002+
/// // Create a value of a type that implements `Unpin`
1003+
/// let mut unpin_future = std::future::ready(5);
1004+
///
1005+
/// // Pin it by creating a pinning mutable reference to it (ready to be `poll`ed!)
1006+
/// let my_pinned_unpin_future: Pin<&mut _> = Pin::new(&mut unpin_future);
1007+
/// ```
9711008
///
9721009
/// ### Pinning a value inside a [`Box`]
9731010
///
974-
/// The simplest and most flexible way to pin a value is to put that value inside a [`Box`] and
975-
/// then turn that [`Box`] into a "pinning [`Box`]" by wrapping it in a [`Pin`].
976-
/// You can do both of these in a single step using [`Box::pin`]. Let's see an example of using
977-
/// this flow to pin a [`Future`] returned from calling an `async fn`, a common use case
978-
/// as described above.
1011+
/// The simplest and most flexible way to pin a value that does not implement [`Unpin`] is to put
1012+
/// that value inside a [`Box`] and then turn that [`Box`] into a "pinning [`Box`]" by wrapping it
1013+
/// in a [`Pin`]. You can do both of these in a single step using [`Box::pin`]. Let's see an
1014+
/// example of using this flow to pin a [`Future`] returned from calling an `async fn`, a common
1015+
/// use case as described above.
9791016
///
9801017
/// ```
9811018
/// use std::pin::Pin;
@@ -1019,8 +1056,8 @@ use crate::{
10191056
///
10201057
/// There are some situations where it is desirable or even required (for example, in a `#[no_std]`
10211058
/// context where you don't have access to the standard library or allocation in general) to
1022-
/// pin a value to its location on the stack. Doing so is possible using the [`pin!`] macro. See
1023-
/// its documentation for more.
1059+
/// pin a value which does not implement [`Unpin`] to its location on the stack. Doing so is
1060+
/// possible using the [`pin!`] macro. See its documentation for more.
10241061
///
10251062
/// ## Layout and ABI
10261063
///
@@ -1033,6 +1070,7 @@ use crate::{
10331070
/// [`pin!`]: crate::pin::pin "pin!"
10341071
/// [`Future`]: crate::future::Future "Future"
10351072
/// [`poll`]: crate::future::Future::poll "Future::poll"
1073+
/// [`Future::poll`]: crate::future::Future::poll "Future::poll"
10361074
/// [`pin` module]: self "pin module"
10371075
/// [`Rc`]: ../../std/rc/struct.Rc.html "Rc"
10381076
/// [`Arc`]: ../../std/sync/struct.Arc.html "Arc"
@@ -1138,7 +1176,10 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
11381176
/// use std::pin::Pin;
11391177
///
11401178
/// let mut val: u8 = 5;
1141-
/// // We can pin the value, since it doesn't care about being moved
1179+
///
1180+
/// // Since `val` doesn't care about being moved, we can safely create a "facade" `Pin`
1181+
/// // which will allow `val` to participate in `Pin`-bound apis without checking that
1182+
/// // pinning guarantees are actually upheld.
11421183
/// let mut pinned: Pin<&mut u8> = Pin::new(&mut val);
11431184
/// ```
11441185
#[inline(always)]
@@ -1162,7 +1203,10 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
11621203
///
11631204
/// let mut val: u8 = 5;
11641205
/// let pinned: Pin<&mut u8> = Pin::new(&mut val);
1165-
/// // Unwrap the pin to get a reference to the value
1206+
///
1207+
/// // Unwrap the pin to get the underlying mutable reference to the value. We can do
1208+
/// // this because `val` doesn't care about being moved, so the `Pin` was just
1209+
/// // a "facade" anyway.
11661210
/// let r = Pin::into_inner(pinned);
11671211
/// assert_eq!(*r, 5);
11681212
/// ```
@@ -1318,7 +1362,7 @@ impl<Ptr: Deref> Pin<Ptr> {
13181362
unsafe { Pin::new_unchecked(&*self.pointer) }
13191363
}
13201364

1321-
/// Unwraps this `Pin<Ptr>` returning the underlying pointer.
1365+
/// Unwraps this `Pin<Ptr>`, returning the underlying `Ptr`.
13221366
///
13231367
/// # Safety
13241368
///
@@ -1331,7 +1375,7 @@ impl<Ptr: Deref> Pin<Ptr> {
13311375
///
13321376
/// Note that you must be able to guarantee that the data pointed to by `Ptr`
13331377
/// will be treated as pinned all the way until its `drop` handler is complete!
1334-
///
1378+
///
13351379
/// *For more information, see the [`pin` module docs][self]*
13361380
///
13371381
/// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used

0 commit comments

Comments
 (0)