@@ -603,101 +603,22 @@ unsafe impl<T: ?Sized> Freeze for *mut T {}
603603unsafe impl < ' a , T : ?Sized > Freeze for & ' a T { }
604604unsafe 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" ) ]
702623pub auto trait Unpin { }
703624
0 commit comments