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