@@ -879,25 +879,28 @@ marker_impls! {
879
879
{ T : ?Sized } & mut T ,
880
880
}
881
881
882
- /// Types that can be safely moved after being pinned .
882
+ /// Types that do not need to follow the rules of pinning .
883
883
///
884
- /// Rust itself has no notion of immovable types, and considers moves (e.g.,
885
- /// through assignment or [`mem::replace`]) to always be safe.
884
+ /// For information on what "pinning" is, see the [`pin` module] documentation.
886
885
///
887
- /// The [`Pin`][Pin] type is used instead to prevent moves through the type
888
- /// system. Pointers `P<T>` wrapped in the [`Pin<P<T>>`][Pin] wrapper can't be
889
- /// moved out of. See the [`pin` module] documentation for more information on
890
- /// pinning.
886
+ /// Implementing the `Unpin` trait for `T` lifts the restrictions of pinning off that type.
887
+ /// This means that, if `T: Unpin`, it cannot be assumed that a value of type `T` will be bound
888
+ /// by the invariants that pinning infers, *even* when "pinned" by a [`Pin<Ptr>`] pointing at it.
889
+ /// When a value of type `T` is pointed at by a [`Pin<Ptr>`], [`Pin`] will not restrict access
890
+ /// to the pointee value like it normally would, thus allowing the user to do anything that they
891
+ /// normally could with a non-[`Pin`]-wrapped `Ptr` to that value.
891
892
///
892
- /// Implementing the `Unpin` trait for `T` lifts the restrictions of pinning off
893
- /// the type, which then allows moving `T` out of [`Pin<P<T>>`][Pin] with
894
- /// functions such as [`mem::replace`].
893
+ /// For more discussion on the consequences of [`Unpin`] within the wider scope of the pinning
894
+ /// system, see [the section about `Unpin`] in the [`pin` module].
895
895
///
896
- /// `Unpin` has no consequence at all for non-pinned data. In particular,
897
- /// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not
898
- /// just when `T: Unpin`). However, you cannot use [`mem::replace`] on data
899
- /// wrapped inside a [`Pin<P<T>>`][Pin] because you cannot get the `&mut T` you
900
- /// need for that, and *that* is what makes this system work.
896
+ /// `Unpin` has no consequence at all for non-pinned data. In particular, [`mem::replace`] happily
897
+ /// moves `!Unpin` data, which would be immovable when pinned ([`mem::replace`] works for any
898
+ /// `&mut T`, not just when `T: Unpin`).
899
+ ///
900
+ /// *However*, you cannot use [`mem::replace`] on `!Unpin` data which is *pinned* by being wrapped
901
+ /// inside a [`Pin<Ptr>`] pointing at it. This is because you cannot (safely) use a
902
+ /// [`Pin<Ptr>`] to get an `&mut T` to its pointee value, which you would need to call
903
+ /// [`mem::replace`], and *that* is what makes this system work.
901
904
///
902
905
/// So this, for example, can only be done on types implementing `Unpin`:
903
906
///
@@ -915,11 +918,20 @@ marker_impls! {
915
918
/// mem::replace(&mut *pinned_string, "other".to_string());
916
919
/// ```
917
920
///
918
- /// This trait is automatically implemented for almost every type.
919
- ///
920
- /// [`mem::replace`]: crate::mem::replace
921
- /// [Pin]: crate::pin::Pin
922
- /// [`pin` module]: crate::pin
921
+ /// This trait is automatically implemented for almost every type. The compiler (and you!) is free
922
+ /// to take the conservative stance of marking types as [`Unpin`] by default. This is because if a
923
+ /// type implements [`Unpin`], then it is unsound for [`unsafe`] code to assume that type is truly
924
+ /// pinned, *even* when viewed through a "pinning" pointer! It is the responsibility of the
925
+ /// implementor of [`unsafe`] code that relies upon pinning for soundness to ensure that all the
926
+ /// types it expects to be truly pinned do not implement [`Unpin`]. For more details, see the
927
+ /// [`pin` module] docs!
928
+ ///
929
+ /// [`mem::replace`]: crate::mem::replace "mem replace"
930
+ /// [`Pin`]: crate::pin::Pin "Pin"
931
+ /// [`Pin<Ptr>`]: crate::pin::Pin "Pin"
932
+ /// [`pin` module]: crate::pin "pin module"
933
+ /// [section about `Unpin`]: crate::pin#unpin "pin module docs about unpin"
934
+ /// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe"
923
935
#[ stable( feature = "pin" , since = "1.33.0" ) ]
924
936
#[ rustc_on_unimplemented(
925
937
note = "consider using the `pin!` macro\n consider using `Box::pin` if you need to access the pinned value outside of the current scope" ,
0 commit comments