Skip to content

Commit c6fd027

Browse files
committed
Auto merge of #58574 - RalfJung:pin, r=Mark-Simulacrum
improve Pin documentation Incorporates a bunch of the documentation-related comments that came up when discussing `Pin` stabilization. Cc @alexcrichton @withoutboats @cramertj @jonhoo Fixes #58130
2 parents d1f8970 + 497439c commit c6fd027

File tree

2 files changed

+310
-49
lines changed

2 files changed

+310
-49
lines changed

src/libcore/marker.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -597,34 +597,43 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
597597

598598
/// Types which can be safely moved after being pinned.
599599
///
600-
/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe,
600+
/// Since Rust itself has no notion of immovable types, and considers moves
601+
/// (e.g. through assignment or [`mem::replace`]) to always be safe,
601602
/// this trait cannot prevent types from moving by itself.
602603
///
603-
/// Instead it can be used to prevent moves through the type system,
604-
/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper,
604+
/// Instead it is used to prevent moves through the type system,
605+
/// by controlling the behavior of pointers `P` wrapped in the [`Pin<P>`] wrapper,
605606
/// which "pin" the type in place by not allowing it to be moved out of them.
606607
/// See the [`pin module`] documentation for more information on pinning.
607608
///
608609
/// Implementing this trait lifts the restrictions of pinning off a type,
609-
/// which then allows it to move out with functions such as [`replace`].
610+
/// which then allows it to move out with functions such as [`mem::replace`].
611+
///
612+
/// `Unpin` has no consequence at all for non-pinned data. In particular,
613+
/// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not
614+
/// just when `T: Unpin`). However, you cannot use
615+
/// [`mem::replace`] on data wrapped inside a [`Pin<P>`] because you cannot get the
616+
/// `&mut T` you need for that, and *that* is what makes this system work.
610617
///
611618
/// So this, for example, can only be done on types implementing `Unpin`:
612619
///
613620
/// ```rust
614-
/// use std::mem::replace;
621+
/// use std::mem;
615622
/// use std::pin::Pin;
616623
///
617624
/// let mut string = "this".to_string();
618625
/// let mut pinned_string = Pin::new(&mut string);
619626
///
620-
/// // dereferencing the pointer mutably is only possible because String implements Unpin
621-
/// replace(&mut *pinned_string, "other".to_string());
627+
/// // We need a mutable reference to call `mem::replace`.
628+
/// // We can obtain such a reference by (implicitly) invoking `Pin::deref_mut`,
629+
/// // but that is only possible because `String` implements `Unpin`.
630+
/// mem::replace(&mut *pinned_string, "other".to_string());
622631
/// ```
623632
///
624633
/// This trait is automatically implemented for almost every type.
625634
///
626-
/// [`replace`]: ../../std/mem/fn.replace.html
627-
/// [`Pin`]: ../pin/struct.Pin.html
635+
/// [`mem::replace`]: ../../std/mem/fn.replace.html
636+
/// [`Pin<P>`]: ../pin/struct.Pin.html
628637
/// [`pin module`]: ../../std/pin/index.html
629638
#[stable(feature = "pin", since = "1.33.0")]
630639
#[cfg_attr(not(stage0), lang = "unpin")]

0 commit comments

Comments
 (0)