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