@@ -603,15 +603,99 @@ unsafe impl<T: ?Sized> Freeze for *mut T {}
603
603
unsafe impl < ' a , T : ?Sized > Freeze for & ' a T { }
604
604
unsafe impl < ' a , T : ?Sized > Freeze for & ' a mut T { }
605
605
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.
607
611
///
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
611
613
///
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`].
613
639
///
614
640
/// [`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
+ /// ```
615
699
#[ unstable( feature = "pin" , issue = "49150" ) ]
616
700
pub auto trait Unpin { }
617
701
0 commit comments