From 94856a7553e6a99eb99f2ee8022df7cb9bcbb2bd Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 15 Nov 2018 15:46:17 -0800 Subject: [PATCH 1/2] Expand documantation for std::pin module --- src/libcore/pin.rs | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index aa5155536c903..256a1d60ac2e5 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -7,23 +7,30 @@ //! since moving an object with pointers to itself will invalidate them, //! which could cause undefined behavior. //! -//! In order to prevent objects from moving, they must be pinned -//! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped -//! in a `Pin` is otherwise equivalent to its normal version, e.g., `Pin>` -//! and `Box` work the same way except that the first is pinning the value -//! of `T` in place. +//! By default, all types in Rust are movable. Rust allows passing all types by-value, +//! and common smart-pointer types such as `Box`, `Rc`, and `&mut` allow replacing and +//! moving the values they contain. In order to prevent objects from moving, they must +//! be pinned by wrapping a pointer to the data in the [`Pin`] type. +//! Doing this prohibits moving the value behind the pointer. +//! For example, `Pin>` functions much like a regular `Box`, +//! but doesn't allow moving `T`. The pointer value itself (the `Box`) can still be moved, +//! but the value behind it cannot. //! -//! First of all, these are pointer types because pinned data mustn't be passed around by value -//! (that would change its location in memory). -//! Secondly, since data can be moved out of `&mut` and `Box` with functions such as [`swap`], -//! which causes their contents to swap places in memory, -//! we need dedicated types that prohibit such operations. +//! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], +//! changing the location of the underlying data, [`Pin`] prohibits accessing the +//! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of +//! APIs for accessing and using the value. //! -//! However, these restrictions are usually not necessary, -//! so most types implement the [`Unpin`] auto-trait, -//! which indicates that the type can be moved out safely. -//! Doing so removes the limitations of pinning types, -//! making them the same as their non-pinning counterparts. +//! However, these restrictions are usually not necessary. Many types are always freely +//! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect +//! of [`Pin`]. For `T: Unpin`, `Pin>` and `Box` function identically, as do +//! `Pin<&mut T>` and `&mut T`. +//! +//! Note that pinning and `Unpin` only affect the pointed-to type. For example, whether +//! or not `Box` is `Unpin` has no affect on the behavior of `Pin>`. Similarly, +//! `Pin>` and `Pin<&mut T>` are always `Unpin` themselves, even though the +//! `T` underneath them isn't, because the pointers in `Pin>` and `Pin<&mut _>` +//! are always freely movable, even if the data they point to isn't. //! //! [`Pin`]: struct.Pin.html //! [`Unpin`]: trait.Unpin.html From 709b7515e744cdf242ab53806414aa295ea6977f Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Thu, 15 Nov 2018 15:49:16 -0800 Subject: [PATCH 2/2] Rename Pinned marker type to PhantomPinned --- src/libcore/marker.rs | 8 ++++---- src/libcore/pin.rs | 11 +++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 0d43f927115f8..d3d16127ed5fe 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -640,15 +640,15 @@ unsafe impl Freeze for &mut T {} #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} -/// A type which does not implement `Unpin`. +/// A marker type which does not implement `Unpin`. /// -/// If a type contains a `Pinned`, it will not implement `Unpin` by default. +/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default. #[unstable(feature = "pin", issue = "49150")] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct Pinned; +pub struct PhantomPinned; #[unstable(feature = "pin", issue = "49150")] -impl !Unpin for Pinned {} +impl !Unpin for PhantomPinned {} #[unstable(feature = "pin", issue = "49150")] impl<'a, T: ?Sized + 'a> Unpin for &'a T {} diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 256a1d60ac2e5..0ad6e8c7c1c7d 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -19,7 +19,10 @@ //! Since data can be moved out of `&mut` and `Box` with functions such as [`swap`], //! changing the location of the underlying data, [`Pin`] prohibits accessing the //! underlying pointer type (the `&mut` or `Box`) directly, and provides its own set of -//! APIs for accessing and using the value. +//! APIs for accessing and using the value. [`Pin`] also guarantees that no other +//! functions will move the pointed-to value. This allows for the creation of +//! self-references and other special behaviors that are only possible for unmovable +//! values. //! //! However, these restrictions are usually not necessary. Many types are always freely //! movable. These types implement the [`Unpin`] auto-trait, which nullifies the affect @@ -43,7 +46,7 @@ //! #![feature(pin)] //! //! use std::pin::Pin; -//! use std::marker::Pinned; +//! use std::marker::PhantomPinned; //! use std::ptr::NonNull; //! //! // This is a self-referential struct since the slice field points to the data field. @@ -54,7 +57,7 @@ //! struct Unmovable { //! data: String, //! slice: NonNull, -//! _pin: Pinned, +//! _pin: PhantomPinned, //! } //! //! impl Unmovable { @@ -67,7 +70,7 @@ //! // we only create the pointer once the data is in place //! // otherwise it will have already moved before we even started //! slice: NonNull::dangling(), -//! _pin: Pinned, +//! _pin: PhantomPinned, //! }; //! let mut boxed = Box::pinned(res); //!