• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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