@@ -603,15 +603,99 @@ 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 which can be moved out of a `PinMut`.
606+ /// A trait that indicates that it is safe to move an object of a type implementing it.
607+ /// Since that is true for most types, it is automatically implemented in most cases.
608+ /// This trait is mainly used to build self referencial structs,
609+ /// since moving an object with pointers to itself will invalidate them,
610+ /// causing undefined behavior.
607611///
608- /// The `Unpin` trait is used to control the behavior of the [`PinMut`] type. If a
609- /// type implements `Unpin`, it is safe to move a value of that type out of the
610- /// `PinMut` pointer.
612+ /// # The Pin API
611613///
612- /// This trait is automatically implemented for almost every type.
614+ /// The `Unpin` trait doesn't actually change the behavior of the compiler around moves,
615+ /// so code like this will compile just fine:
616+ ///
617+ /// ```rust
618+ /// #![feature(pin)]
619+ /// use std::marker::Pinned;
620+ ///
621+ /// struct Unmovable {
622+ /// _pin: Pinned, // this marker type prevents Unpin from being implemented for this type
623+ /// }
624+ ///
625+ /// let unmoved = Unmovable { _pin: Pinned };
626+ /// let moved = unmoved;
627+ /// ```
628+ ///
629+ /// In order to actually prevent the pinned objects from moving,
630+ /// it has to be wrapped in special pointer types,
631+ /// which currently include [`PinMut`] and [`PinBox`].
632+ ///
633+ /// The way they work is by implementing [`DerefMut`] for all types that implement Unpin,
634+ /// but only [`Deref`] otherwise.
635+ ///
636+ /// This is done because, while modifying an object can be done in-place,
637+ /// it might also relocate a buffer when its at full capacity,
638+ /// or it might replace one object with another without logically "moving" them with [`swap`].
613639///
614640/// [`PinMut`]: ../mem/struct.PinMut.html
641+ /// [`PinBox`]: ../../alloc/boxed/struct.PinMut.html
642+ /// [`DerefMut`]: ../ops/trait.DerefMut.html
643+ /// [`Deref`]: ../ops/trait.Deref.html
644+ /// [`swap`]: ../mem/fn.swap.html
645+ ///
646+ /// # example
647+ ///
648+ /// ```rust
649+ /// #![feature(pin)]
650+ ///
651+ /// use std::boxed::PinBox;
652+ /// use std::marker::Pinned;
653+ /// use std::ptr::NonNull;
654+ ///
655+ /// // this is a self referencial struct since the slice field points to the data field.
656+ /// // we cannot inform the compiler about that with a normal reference,
657+ /// // since moving the data with it that would violate borrowing rules.
658+ /// // instead we use a raw pointer, though one which is known to not be null,
659+ /// // since we know its pointing at the string.
660+ /// struct Unmovable {
661+ /// data: String,
662+ /// slice: NonNull<String>,
663+ /// _pin: Pinned,
664+ /// }
665+ ///
666+ /// impl Unmovable {
667+ /// // to ensure the data doesn't move when the function returns,
668+ /// // we place it in the heap where it will stay for the lifetime of the object,
669+ /// // and the only way to access it would be through a pointer to it
670+ /// fn new(data: String) -> PinBox<Self> {
671+ /// let res = Unmovable {
672+ /// data,
673+ /// // we only create the pointer once the data is in place
674+ /// // otherwise it will have already moved before we even started
675+ /// slice: NonNull::dangling(),
676+ /// _pin: Pinned,
677+ /// };
678+ /// let mut boxed = PinBox::new(res);
679+ ///
680+ /// let slice = NonNull::from(&boxed.data);
681+ /// // we know this is safe because modifying a field doesn't move the whole struct
682+ /// unsafe { PinBox::get_mut(&mut boxed).slice = slice };
683+ /// boxed
684+ /// }
685+ /// }
686+ ///
687+ /// let unmoved = Unmovable::new("hello".to_string());
688+ /// // the pointer should point to the correct location,
689+ /// // so long as the struct hasn't moved.
690+ /// // meanwhile, we are free to move the pointer around
691+ /// let mut still_unmoved = unmoved;
692+ /// assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));
693+ ///
694+ /// // now the only way to access to data (safely) is immutably,
695+ /// // so this will fail to compile:
696+ /// // still_unmoved.data.push_str(" world");
697+ ///
698+ /// ```
615699#[ unstable( feature = "pin" , issue = "49150" ) ]
616700pub auto trait Unpin { }
617701
0 commit comments