about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiv Kaminer <nivkner@zoho.com>2018-08-07 21:14:57 +0300
committerNiv Kaminer <nivkner@zoho.com>2018-08-07 21:14:57 +0300
commit68e766afab32a45e55728e11c17b996848a7dd49 (patch)
treea56d88f250843512bef610da7626f8f93d336a62
parent87bbd2eeef1ad321b294e2d3b0fb2dc960390c86 (diff)
downloadrust-68e766afab32a45e55728e11c17b996848a7dd49.tar.gz
rust-68e766afab32a45e55728e11c17b996848a7dd49.zip
remove general pinning information from Unpin trait
-rw-r--r--src/libcore/marker.rs97
1 files changed, 9 insertions, 88 deletions
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index d398ca62157..596727a0141 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -603,101 +603,22 @@ unsafe impl<T: ?Sized> Freeze for *mut T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 
-/// Types that are safe to move.
+/// Types which can be safely moved after being pinned.
 ///
-/// Since moving objects is almost always safe, it is automatically implemented in most cases.
+/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe,
+/// this trait cannot prevent types from moving by itself.
 ///
-/// This trait is mainly used to build self referencial structs,
-/// since moving an object with pointers to itself will invalidate them,
-/// causing undefined behavior.
+/// Instead it can be used to prevent moves through the type system,
+/// by controlling the behavior of special pointers types like [`PinMut`],
+/// which "pin" the type in place by wrapping it in a type which can only be dereferenced immutably.
 ///
-/// # The Pin API
+/// Implementing this trait lifts the restrictions of pinning off a type,
+/// which then allows it to move out of said pointers with functions such as [`swap`].
 ///
-/// The `Unpin` trait doesn't actually change the behavior of the compiler around moves,
-/// so code like this will compile just fine:
-///
-/// ```rust
-/// #![feature(pin)]
-/// use std::marker::Pinned;
-///
-/// struct Unmovable {
-///     _pin: Pinned, // this marker type prevents Unpin from being implemented for this type
-/// }
-///
-/// let unmoved = Unmovable { _pin: Pinned };
-/// let moved = unmoved;
-/// ```
-///
-/// In order to actually prevent the pinned objects from moving,
-/// it has to be wrapped in special pointer types,
-/// which currently include [`PinMut`] and [`PinBox`].
-///
-/// The way they work is by implementing [`DerefMut`] for all types that implement Unpin,
-/// but only [`Deref`] otherwise.
-///
-/// This is done because, while modifying an object can be done in-place,
-/// it might also relocate a buffer when its at full capacity,
-/// or it might replace one object with another without logically "moving" them with [`swap`].
+/// This trait is automatically implemented for almost every type.
 ///
 /// [`PinMut`]: ../mem/struct.PinMut.html
-/// [`PinBox`]: ../../alloc/boxed/struct.PinBox.html
-/// [`DerefMut`]: ../ops/trait.DerefMut.html
-/// [`Deref`]: ../ops/trait.Deref.html
 /// [`swap`]: ../mem/fn.swap.html
-///
-/// # Examples
-///
-/// ```rust
-/// #![feature(pin)]
-///
-/// use std::boxed::PinBox;
-/// use std::marker::Pinned;
-/// use std::ptr::NonNull;
-///
-/// // This is a self referencial struct since the slice field points to the data field.
-/// // We cannot inform the compiler about that with a normal reference,
-/// // since this pattern cannot be described with the usual borrowing rules.
-/// // Instead we use a raw pointer, though one which is known to not be null,
-/// // since we know it's pointing at the string.
-/// struct Unmovable {
-///     data: String,
-///     slice: NonNull<String>,
-///     _pin: Pinned,
-/// }
-///
-/// impl Unmovable {
-///     // To ensure the data doesn't move when the function returns,
-///     // we place it in the heap where it will stay for the lifetime of the object,
-///     // and the only way to access it would be through a pointer to it.
-///     fn new(data: String) -> PinBox<Self> {
-///         let res = Unmovable {
-///             data,
-///             // 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,
-///         };
-///         let mut boxed = PinBox::new(res);
-///
-///         let slice = NonNull::from(&boxed.data);
-///         // we know this is safe because modifying a field doesn't move the whole struct
-///         unsafe { PinBox::get_mut(&mut boxed).slice = slice };
-///         boxed
-///     }
-/// }
-///
-/// let unmoved = Unmovable::new("hello".to_string());
-/// // The pointer should point to the correct location,
-/// // so long as the struct hasn't moved.
-/// // Meanwhile, we are free to move the pointer around.
-/// let mut still_unmoved = unmoved;
-/// assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
-///
-/// // Now the only way to access to data (safely) is immutably,
-/// // so this will fail to compile:
-/// // still_unmoved.data.push_str(" world");
-///
-/// ```
 #[unstable(feature = "pin", issue = "49150")]
 pub auto trait Unpin {}