@@ -603,101 +603,22 @@ 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 that are safe to move .
606
+ /// Types which can be safely moved after being pinned .
607
607
///
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.
609
610
///
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 .
613
614
///
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`].
615
617
///
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.
641
619
///
642
620
/// [`PinMut`]: ../mem/struct.PinMut.html
643
- /// [`PinBox`]: ../../alloc/boxed/struct.PinBox.html
644
- /// [`DerefMut`]: ../ops/trait.DerefMut.html
645
- /// [`Deref`]: ../ops/trait.Deref.html
646
621
/// [`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
- /// ```
701
622
#[ unstable( feature = "pin" , issue = "49150" ) ]
702
623
pub auto trait Unpin { }
703
624
0 commit comments