Skip to content

Commit 68e766a

Browse files
committed
remove general pinning information from Unpin trait
1 parent 87bbd2e commit 68e766a

File tree

1 file changed

+9
-88
lines changed

1 file changed

+9
-88
lines changed

src/libcore/marker.rs

Lines changed: 9 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -603,101 +603,22 @@ unsafe impl<T: ?Sized> Freeze for *mut T {}
603603
unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
604604
unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
605605

606-
/// Types that are safe to move.
606+
/// Types which can be safely moved after being pinned.
607607
///
608-
/// Since moving objects is almost always safe, it is automatically implemented in most cases.
608+
/// Since Rust itself has no notion of immovable types, and will consider moves to always be safe,
609+
/// this trait cannot prevent types from moving by itself.
609610
///
610-
/// This trait is mainly used to build self referencial structs,
611-
/// since moving an object with pointers to itself will invalidate them,
612-
/// causing undefined behavior.
611+
/// Instead it can be used to prevent moves through the type system,
612+
/// by controlling the behavior of special pointers types like [`PinMut`],
613+
/// which "pin" the type in place by wrapping it in a type which can only be dereferenced immutably.
613614
///
614-
/// # The Pin API
615+
/// Implementing this trait lifts the restrictions of pinning off a type,
616+
/// which then allows it to move out of said pointers with functions such as [`swap`].
615617
///
616-
/// The `Unpin` trait doesn't actually change the behavior of the compiler around moves,
617-
/// so code like this will compile just fine:
618-
///
619-
/// ```rust
620-
/// #![feature(pin)]
621-
/// use std::marker::Pinned;
622-
///
623-
/// struct Unmovable {
624-
/// _pin: Pinned, // this marker type prevents Unpin from being implemented for this type
625-
/// }
626-
///
627-
/// let unmoved = Unmovable { _pin: Pinned };
628-
/// let moved = unmoved;
629-
/// ```
630-
///
631-
/// In order to actually prevent the pinned objects from moving,
632-
/// it has to be wrapped in special pointer types,
633-
/// which currently include [`PinMut`] and [`PinBox`].
634-
///
635-
/// The way they work is by implementing [`DerefMut`] for all types that implement Unpin,
636-
/// but only [`Deref`] otherwise.
637-
///
638-
/// This is done because, while modifying an object can be done in-place,
639-
/// it might also relocate a buffer when its at full capacity,
640-
/// or it might replace one object with another without logically "moving" them with [`swap`].
618+
/// This trait is automatically implemented for almost every type.
641619
///
642620
/// [`PinMut`]: ../mem/struct.PinMut.html
643-
/// [`PinBox`]: ../../alloc/boxed/struct.PinBox.html
644-
/// [`DerefMut`]: ../ops/trait.DerefMut.html
645-
/// [`Deref`]: ../ops/trait.Deref.html
646621
/// [`swap`]: ../mem/fn.swap.html
647-
///
648-
/// # Examples
649-
///
650-
/// ```rust
651-
/// #![feature(pin)]
652-
///
653-
/// use std::boxed::PinBox;
654-
/// use std::marker::Pinned;
655-
/// use std::ptr::NonNull;
656-
///
657-
/// // This is a self referencial struct since the slice field points to the data field.
658-
/// // We cannot inform the compiler about that with a normal reference,
659-
/// // since this pattern cannot be described with the usual borrowing rules.
660-
/// // Instead we use a raw pointer, though one which is known to not be null,
661-
/// // since we know it's pointing at the string.
662-
/// struct Unmovable {
663-
/// data: String,
664-
/// slice: NonNull<String>,
665-
/// _pin: Pinned,
666-
/// }
667-
///
668-
/// impl Unmovable {
669-
/// // To ensure the data doesn't move when the function returns,
670-
/// // we place it in the heap where it will stay for the lifetime of the object,
671-
/// // and the only way to access it would be through a pointer to it.
672-
/// fn new(data: String) -> PinBox<Self> {
673-
/// let res = Unmovable {
674-
/// data,
675-
/// // we only create the pointer once the data is in place
676-
/// // otherwise it will have already moved before we even started
677-
/// slice: NonNull::dangling(),
678-
/// _pin: Pinned,
679-
/// };
680-
/// let mut boxed = PinBox::new(res);
681-
///
682-
/// let slice = NonNull::from(&boxed.data);
683-
/// // we know this is safe because modifying a field doesn't move the whole struct
684-
/// unsafe { PinBox::get_mut(&mut boxed).slice = slice };
685-
/// boxed
686-
/// }
687-
/// }
688-
///
689-
/// let unmoved = Unmovable::new("hello".to_string());
690-
/// // The pointer should point to the correct location,
691-
/// // so long as the struct hasn't moved.
692-
/// // Meanwhile, we are free to move the pointer around.
693-
/// let mut still_unmoved = unmoved;
694-
/// assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
695-
///
696-
/// // Now the only way to access to data (safely) is immutably,
697-
/// // so this will fail to compile:
698-
/// // still_unmoved.data.push_str(" world");
699-
///
700-
/// ```
701622
#[unstable(feature = "pin", issue = "49150")]
702623
pub auto trait Unpin {}
703624

0 commit comments

Comments
 (0)