1 /// A pinned projection of a struct field. 2 /// 3 /// To make using this macro safe, three things need to be ensured: 4 /// - If the struct implements [`Drop`], the [`drop`] method is not allowed to 5 /// move the value of the field. 6 /// - If the struct wants to implement [`Unpin`], it has to do so conditionally: 7 /// The struct can only implement [`Unpin`] if the field's type is [`Unpin`]. 8 /// - The struct must not be `#[repr(packed)]`. 9 /// 10 /// ``` 11 /// use pin_utils::unsafe_pinned; 12 /// use std::marker::Unpin; 13 /// use std::pin::Pin; 14 /// 15 /// struct Foo<T> { 16 /// field: T, 17 /// } 18 /// 19 /// impl<T> Foo<T> { 20 /// unsafe_pinned!(field: T); 21 /// 22 /// fn baz(mut self: Pin<&mut Self>) { 23 /// let _: Pin<&mut T> = self.field(); // Pinned reference to the field 24 /// } 25 /// } 26 /// 27 /// impl<T: Unpin> Unpin for Foo<T> {} // Conditional Unpin impl 28 /// ``` 29 /// 30 /// Note that borrowing the field multiple times requires using `.as_mut()` to 31 /// avoid consuming the `Pin`. 32 /// 33 /// [`Unpin`]: core::marker::Unpin 34 /// [`drop`]: Drop::drop 35 #[macro_export] 36 macro_rules! unsafe_pinned { 37 ($f:tt: $t:ty) => ( 38 fn $f<'__a>( 39 self: $crate::core_reexport::pin::Pin<&'__a mut Self> 40 ) -> $crate::core_reexport::pin::Pin<&'__a mut $t> { 41 unsafe { 42 $crate::core_reexport::pin::Pin::map_unchecked_mut( 43 self, |x| &mut x.$f 44 ) 45 } 46 } 47 ) 48 } 49 50 /// An unpinned projection of a struct field. 51 /// 52 /// This macro is unsafe because it creates a method that returns a normal 53 /// non-pin reference to the struct field. It is up to the programmer to ensure 54 /// that the contained value can be considered not pinned in the current 55 /// context. 56 /// 57 /// Note that borrowing the field multiple times requires using `.as_mut()` to 58 /// avoid consuming the `Pin`. 59 /// 60 /// ``` 61 /// use pin_utils::unsafe_unpinned; 62 /// use std::pin::Pin; 63 /// 64 /// struct Bar; 65 /// struct Foo { 66 /// field: Bar, 67 /// } 68 /// 69 /// impl Foo { 70 /// unsafe_unpinned!(field: Bar); 71 /// 72 /// fn baz(mut self: Pin<&mut Self>) { 73 /// let _: &mut Bar = self.field(); // Normal reference to the field 74 /// } 75 /// } 76 /// ``` 77 #[macro_export] 78 macro_rules! unsafe_unpinned { 79 ($f:tt: $t:ty) => ( 80 fn $f<'__a>( 81 self: $crate::core_reexport::pin::Pin<&'__a mut Self> 82 ) -> &'__a mut $t { 83 unsafe { 84 &mut $crate::core_reexport::pin::Pin::get_unchecked_mut(self).$f 85 } 86 } 87 ) 88 } 89