xref: /openbmc/linux/rust/kernel/init/macros.rs (revision fc6c6baa1f40ded13e539d0c1a17bcefc00abad9)
1*fc6c6baaSBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
2*fc6c6baaSBenno Lossin 
3*fc6c6baaSBenno Lossin //! This module provides the macros that actually implement the proc-macros `pin_data` and
4*fc6c6baaSBenno Lossin //! `pinned_drop`.
5*fc6c6baaSBenno Lossin //!
6*fc6c6baaSBenno Lossin //! These macros should never be called directly, since they expect their input to be
7*fc6c6baaSBenno Lossin //! in a certain format which is internal. Use the proc-macros instead.
8*fc6c6baaSBenno Lossin //!
9*fc6c6baaSBenno Lossin //! This architecture has been chosen because the kernel does not yet have access to `syn` which
10*fc6c6baaSBenno Lossin //! would make matters a lot easier for implementing these as proc-macros.
11*fc6c6baaSBenno Lossin //!
12*fc6c6baaSBenno Lossin //! # Macro expansion example
13*fc6c6baaSBenno Lossin //!
14*fc6c6baaSBenno Lossin //! This section is intended for readers trying to understand the macros in this module and the
15*fc6c6baaSBenno Lossin //! `pin_init!` macros from `init.rs`.
16*fc6c6baaSBenno Lossin //!
17*fc6c6baaSBenno Lossin //! We will look at the following example:
18*fc6c6baaSBenno Lossin //!
19*fc6c6baaSBenno Lossin //! ```rust
20*fc6c6baaSBenno Lossin //! # use kernel::init::*;
21*fc6c6baaSBenno Lossin //! #[pin_data]
22*fc6c6baaSBenno Lossin //! #[repr(C)]
23*fc6c6baaSBenno Lossin //! struct Bar<T> {
24*fc6c6baaSBenno Lossin //!     #[pin]
25*fc6c6baaSBenno Lossin //!     t: T,
26*fc6c6baaSBenno Lossin //!     pub x: usize,
27*fc6c6baaSBenno Lossin //! }
28*fc6c6baaSBenno Lossin //!
29*fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
30*fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
31*fc6c6baaSBenno Lossin //!         pin_init!(Self { t, x: 0 })
32*fc6c6baaSBenno Lossin //!     }
33*fc6c6baaSBenno Lossin //! }
34*fc6c6baaSBenno Lossin //! ```
35*fc6c6baaSBenno Lossin //!
36*fc6c6baaSBenno Lossin //! This example includes the most common and important features of the pin-init API.
37*fc6c6baaSBenno Lossin //!
38*fc6c6baaSBenno Lossin //! Below you can find individual section about the different macro invocations. Here are some
39*fc6c6baaSBenno Lossin //! general things we need to take into account when designing macros:
40*fc6c6baaSBenno Lossin //! - use global paths, similarly to file paths, these start with the separator: `::core::panic!()`
41*fc6c6baaSBenno Lossin //!   this ensures that the correct item is used, since users could define their own `mod core {}`
42*fc6c6baaSBenno Lossin //!   and then their own `panic!` inside to execute arbitrary code inside of our macro.
43*fc6c6baaSBenno Lossin //! - macro `unsafe` hygiene: we need to ensure that we do not expand arbitrary, user-supplied
44*fc6c6baaSBenno Lossin //!   expressions inside of an `unsafe` block in the macro, because this would allow users to do
45*fc6c6baaSBenno Lossin //!   `unsafe` operations without an associated `unsafe` block.
46*fc6c6baaSBenno Lossin //!
47*fc6c6baaSBenno Lossin //! ## `#[pin_data]` on `Bar`
48*fc6c6baaSBenno Lossin //!
49*fc6c6baaSBenno Lossin //! This macro is used to specify which fields are structurally pinned and which fields are not. It
50*fc6c6baaSBenno Lossin //! is placed on the struct definition and allows `#[pin]` to be placed on the fields.
51*fc6c6baaSBenno Lossin //!
52*fc6c6baaSBenno Lossin //! Here is the definition of `Bar` from our example:
53*fc6c6baaSBenno Lossin //!
54*fc6c6baaSBenno Lossin //! ```rust
55*fc6c6baaSBenno Lossin //! # use kernel::init::*;
56*fc6c6baaSBenno Lossin //! #[pin_data]
57*fc6c6baaSBenno Lossin //! #[repr(C)]
58*fc6c6baaSBenno Lossin //! struct Bar<T> {
59*fc6c6baaSBenno Lossin //!     t: T,
60*fc6c6baaSBenno Lossin //!     pub x: usize,
61*fc6c6baaSBenno Lossin //! }
62*fc6c6baaSBenno Lossin //! ```
63*fc6c6baaSBenno Lossin //!
64*fc6c6baaSBenno Lossin //! This expands to the following code:
65*fc6c6baaSBenno Lossin //!
66*fc6c6baaSBenno Lossin //! ```rust
67*fc6c6baaSBenno Lossin //! // Firstly the normal definition of the struct, attributes are preserved:
68*fc6c6baaSBenno Lossin //! #[repr(C)]
69*fc6c6baaSBenno Lossin //! struct Bar<T> {
70*fc6c6baaSBenno Lossin //!     t: T,
71*fc6c6baaSBenno Lossin //!     pub x: usize,
72*fc6c6baaSBenno Lossin //! }
73*fc6c6baaSBenno Lossin //! // Then an anonymous constant is defined, this is because we do not want any code to access the
74*fc6c6baaSBenno Lossin //! // types that we define inside:
75*fc6c6baaSBenno Lossin //! const _: () = {
76*fc6c6baaSBenno Lossin //!     // We define the pin-data carrying struct, it is a ZST and needs to have the same generics,
77*fc6c6baaSBenno Lossin //!     // since we need to implement access functions for each field and thus need to know its
78*fc6c6baaSBenno Lossin //!     // type.
79*fc6c6baaSBenno Lossin //!     struct __ThePinData<T> {
80*fc6c6baaSBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
81*fc6c6baaSBenno Lossin //!     }
82*fc6c6baaSBenno Lossin //!     // We implement `Copy` for the pin-data struct, since all functions it defines will take
83*fc6c6baaSBenno Lossin //!     // `self` by value.
84*fc6c6baaSBenno Lossin //!     impl<T> ::core::clone::Clone for __ThePinData<T> {
85*fc6c6baaSBenno Lossin //!         fn clone(&self) -> Self {
86*fc6c6baaSBenno Lossin //!             *self
87*fc6c6baaSBenno Lossin //!         }
88*fc6c6baaSBenno Lossin //!     }
89*fc6c6baaSBenno Lossin //!     impl<T> ::core::marker::Copy for __ThePinData<T> {}
90*fc6c6baaSBenno Lossin //!     // For every field of `Bar`, the pin-data struct will define a function with the same name
91*fc6c6baaSBenno Lossin //!     // and accessor (`pub` or `pub(crate)` etc.). This function will take a pointer to the
92*fc6c6baaSBenno Lossin //!     // field (`slot`) and a `PinInit` or `Init` depending on the projection kind of the field
93*fc6c6baaSBenno Lossin //!     // (if pinning is structural for the field, then `PinInit` otherwise `Init`).
94*fc6c6baaSBenno Lossin //!     #[allow(dead_code)]
95*fc6c6baaSBenno Lossin //!     impl<T> __ThePinData<T> {
96*fc6c6baaSBenno Lossin //!         unsafe fn t<E>(
97*fc6c6baaSBenno Lossin //!             self,
98*fc6c6baaSBenno Lossin //!             slot: *mut T,
99*fc6c6baaSBenno Lossin //!             init: impl ::kernel::init::Init<T, E>,
100*fc6c6baaSBenno Lossin //!         ) -> ::core::result::Result<(), E> {
101*fc6c6baaSBenno Lossin //!             unsafe { ::kernel::init::Init::__init(init, slot) }
102*fc6c6baaSBenno Lossin //!         }
103*fc6c6baaSBenno Lossin //!         pub unsafe fn x<E>(
104*fc6c6baaSBenno Lossin //!             self,
105*fc6c6baaSBenno Lossin //!             slot: *mut usize,
106*fc6c6baaSBenno Lossin //!             init: impl ::kernel::init::Init<usize, E>,
107*fc6c6baaSBenno Lossin //!         ) -> ::core::result::Result<(), E> {
108*fc6c6baaSBenno Lossin //!             unsafe { ::kernel::init::Init::__init(init, slot) }
109*fc6c6baaSBenno Lossin //!         }
110*fc6c6baaSBenno Lossin //!     }
111*fc6c6baaSBenno Lossin //!     // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct
112*fc6c6baaSBenno Lossin //!     // that we constructed beforehand.
113*fc6c6baaSBenno Lossin //!     unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> {
114*fc6c6baaSBenno Lossin //!         type PinData = __ThePinData<T>;
115*fc6c6baaSBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
116*fc6c6baaSBenno Lossin //!             __ThePinData {
117*fc6c6baaSBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
118*fc6c6baaSBenno Lossin //!             }
119*fc6c6baaSBenno Lossin //!         }
120*fc6c6baaSBenno Lossin //!     }
121*fc6c6baaSBenno Lossin //!     // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data
122*fc6c6baaSBenno Lossin //!     // struct. This is important to ensure that no user can implement a rouge `__pin_data`
123*fc6c6baaSBenno Lossin //!     // function without using `unsafe`.
124*fc6c6baaSBenno Lossin //!     unsafe impl<T> ::kernel::init::__internal::PinData for __ThePinData<T> {
125*fc6c6baaSBenno Lossin //!         type Datee = Bar<T>;
126*fc6c6baaSBenno Lossin //!     }
127*fc6c6baaSBenno Lossin //!     // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is
128*fc6c6baaSBenno Lossin //!     // `Unpin`. In other words, whether `Bar` is `Unpin` only depends on structurally pinned
129*fc6c6baaSBenno Lossin //!     // fields (those marked with `#[pin]`). These fields will be listed in this struct, in our
130*fc6c6baaSBenno Lossin //!     // case no such fields exist, hence this is almost empty. The two phantomdata fields exist
131*fc6c6baaSBenno Lossin //!     // for two reasons:
132*fc6c6baaSBenno Lossin //!     // - `__phantom`: every generic must be used, since we cannot really know which generics
133*fc6c6baaSBenno Lossin //!     //   are used, we declere all and then use everything here once.
134*fc6c6baaSBenno Lossin //!     // - `__phantom_pin`: uses the `'__pin` lifetime and ensures that this struct is invariant
135*fc6c6baaSBenno Lossin //!     //   over it. The lifetime is needed to work around the limitation that trait bounds must
136*fc6c6baaSBenno Lossin //!     //   not be trivial, e.g. the user has a `#[pin] PhantomPinned` field -- this is
137*fc6c6baaSBenno Lossin //!     //   unconditionally `!Unpin` and results in an error. The lifetime tricks the compiler
138*fc6c6baaSBenno Lossin //!     //   into accepting these bounds regardless.
139*fc6c6baaSBenno Lossin //!     #[allow(dead_code)]
140*fc6c6baaSBenno Lossin //!     struct __Unpin<'__pin, T> {
141*fc6c6baaSBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
142*fc6c6baaSBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
143*fc6c6baaSBenno Lossin //!     }
144*fc6c6baaSBenno Lossin //!     #[doc(hidden)]
145*fc6c6baaSBenno Lossin //!     impl<'__pin, T>
146*fc6c6baaSBenno Lossin //!         ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {}
147*fc6c6baaSBenno Lossin //!     // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
148*fc6c6baaSBenno Lossin //!     // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
149*fc6c6baaSBenno Lossin //!     // UB with only safe code, so we disallow this by giving a trait implementation error using
150*fc6c6baaSBenno Lossin //!     // a direct impl and a blanket implementation.
151*fc6c6baaSBenno Lossin //!     trait MustNotImplDrop {}
152*fc6c6baaSBenno Lossin //!     // Normally `Drop` bounds do not have the correct semantics, but for this purpose they do
153*fc6c6baaSBenno Lossin //!     // (normally people want to know if a type has any kind of drop glue at all, here we want
154*fc6c6baaSBenno Lossin //!     // to know if it has any kind of custom drop glue, which is exactly what this bound does).
155*fc6c6baaSBenno Lossin //!     #[allow(drop_bounds)]
156*fc6c6baaSBenno Lossin //!     impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
157*fc6c6baaSBenno Lossin //!     impl<T> MustNotImplDrop for Bar<T> {}
158*fc6c6baaSBenno Lossin //! };
159*fc6c6baaSBenno Lossin //! ```
160*fc6c6baaSBenno Lossin //!
161*fc6c6baaSBenno Lossin //! ## `pin_init!` in `impl Bar`
162*fc6c6baaSBenno Lossin //!
163*fc6c6baaSBenno Lossin //! This macro creates an pin-initializer for the given struct. It requires that the struct is
164*fc6c6baaSBenno Lossin //! annotated by `#[pin_data]`.
165*fc6c6baaSBenno Lossin //!
166*fc6c6baaSBenno Lossin //! Here is the impl on `Bar` defining the new function:
167*fc6c6baaSBenno Lossin //!
168*fc6c6baaSBenno Lossin //! ```rust
169*fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
170*fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
171*fc6c6baaSBenno Lossin //!         pin_init!(Self { t, x: 0 })
172*fc6c6baaSBenno Lossin //!     }
173*fc6c6baaSBenno Lossin //! }
174*fc6c6baaSBenno Lossin //! ```
175*fc6c6baaSBenno Lossin //!
176*fc6c6baaSBenno Lossin //! This expands to the following code:
177*fc6c6baaSBenno Lossin //!
178*fc6c6baaSBenno Lossin //! ```rust
179*fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
180*fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
181*fc6c6baaSBenno Lossin //!         {
182*fc6c6baaSBenno Lossin //!             // We do not want to allow arbitrary returns, so we declare this type as the `Ok`
183*fc6c6baaSBenno Lossin //!             // return type and shadow it later when we insert the arbitrary user code. That way
184*fc6c6baaSBenno Lossin //!             // there will be no possibility of returning without `unsafe`.
185*fc6c6baaSBenno Lossin //!             struct __InitOk;
186*fc6c6baaSBenno Lossin //!             // Get the pin-data type from the initialized type.
187*fc6c6baaSBenno Lossin //!             // - the function is unsafe, hence the unsafe block
188*fc6c6baaSBenno Lossin //!             // - we `use` the `HasPinData` trait in the block, it is only available in that
189*fc6c6baaSBenno Lossin //!             //   scope.
190*fc6c6baaSBenno Lossin //!             let data = unsafe {
191*fc6c6baaSBenno Lossin //!                 use ::kernel::init::__internal::HasPinData;
192*fc6c6baaSBenno Lossin //!                 Self::__pin_data()
193*fc6c6baaSBenno Lossin //!             };
194*fc6c6baaSBenno Lossin //!             // Use `data` to help with type inference, the closure supplied will have the type
195*fc6c6baaSBenno Lossin //!             // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`.
196*fc6c6baaSBenno Lossin //!             let init = ::kernel::init::__internal::PinData::make_closure::<
197*fc6c6baaSBenno Lossin //!                 _,
198*fc6c6baaSBenno Lossin //!                 __InitOk,
199*fc6c6baaSBenno Lossin //!                 ::core::convert::Infallible,
200*fc6c6baaSBenno Lossin //!             >(data, move |slot| {
201*fc6c6baaSBenno Lossin //!                 {
202*fc6c6baaSBenno Lossin //!                     // Shadow the structure so it cannot be used to return early. If a user
203*fc6c6baaSBenno Lossin //!                     // tries to write `return Ok(__InitOk)`, then they get a type error, since
204*fc6c6baaSBenno Lossin //!                     // that will refer to this struct instead of the one defined above.
205*fc6c6baaSBenno Lossin //!                     struct __InitOk;
206*fc6c6baaSBenno Lossin //!                     // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
207*fc6c6baaSBenno Lossin //!                     unsafe { ::core::ptr::write(&raw mut (*slot).t, t) };
208*fc6c6baaSBenno Lossin //!                     // Since initialization could fail later (not in this case, since the error
209*fc6c6baaSBenno Lossin //!                     // type is `Infallible`) we will need to drop this field if it fails. This
210*fc6c6baaSBenno Lossin //!                     // `DropGuard` will drop the field when it gets dropped and has not yet
211*fc6c6baaSBenno Lossin //!                     // been forgotten. We make a reference to it, so users cannot `mem::forget`
212*fc6c6baaSBenno Lossin //!                     // it from the initializer, since the name is the same as the field.
213*fc6c6baaSBenno Lossin //!                     let t = &unsafe {
214*fc6c6baaSBenno Lossin //!                         ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).t)
215*fc6c6baaSBenno Lossin //!                     };
216*fc6c6baaSBenno Lossin //!                     // Expansion of `x: 0,`:
217*fc6c6baaSBenno Lossin //!                     // Since this can be an arbitrary expression we cannot place it inside of
218*fc6c6baaSBenno Lossin //!                     // the `unsafe` block, so we bind it here.
219*fc6c6baaSBenno Lossin //!                     let x = 0;
220*fc6c6baaSBenno Lossin //!                     unsafe { ::core::ptr::write(&raw mut (*slot).x, x) };
221*fc6c6baaSBenno Lossin //!                     let x = &unsafe {
222*fc6c6baaSBenno Lossin //!                         ::kernel::init::__internal::DropGuard::new(&raw mut (*slot).x)
223*fc6c6baaSBenno Lossin //!                     };
224*fc6c6baaSBenno Lossin //!
225*fc6c6baaSBenno Lossin //!                     // Here we use the type checker to ensuer that every field has been
226*fc6c6baaSBenno Lossin //!                     // initialized exactly once, since this is `if false` it will never get
227*fc6c6baaSBenno Lossin //!                     // executed, but still type-checked.
228*fc6c6baaSBenno Lossin //!                     // Additionally we abuse `slot` to automatically infer the correct type for
229*fc6c6baaSBenno Lossin //!                     // the struct. This is also another check that every field is accessible
230*fc6c6baaSBenno Lossin //!                     // from this scope.
231*fc6c6baaSBenno Lossin //!                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
232*fc6c6baaSBenno Lossin //!                     if false {
233*fc6c6baaSBenno Lossin //!                         unsafe {
234*fc6c6baaSBenno Lossin //!                             ::core::ptr::write(
235*fc6c6baaSBenno Lossin //!                                 slot,
236*fc6c6baaSBenno Lossin //!                                 Self {
237*fc6c6baaSBenno Lossin //!                                     // We only care about typecheck finding every field here,
238*fc6c6baaSBenno Lossin //!                                     // the expression does not matter, just conjure one using
239*fc6c6baaSBenno Lossin //!                                     // `panic!()`:
240*fc6c6baaSBenno Lossin //!                                     t: ::core::panic!(),
241*fc6c6baaSBenno Lossin //!                                     x: ::core::panic!(),
242*fc6c6baaSBenno Lossin //!                                 },
243*fc6c6baaSBenno Lossin //!                             );
244*fc6c6baaSBenno Lossin //!                         };
245*fc6c6baaSBenno Lossin //!                     }
246*fc6c6baaSBenno Lossin //!                     // Since initialization has successfully completed, we can now forget the
247*fc6c6baaSBenno Lossin //!                     // guards.
248*fc6c6baaSBenno Lossin //!                     unsafe { ::kernel::init::__internal::DropGuard::forget(t) };
249*fc6c6baaSBenno Lossin //!                     unsafe { ::kernel::init::__internal::DropGuard::forget(x) };
250*fc6c6baaSBenno Lossin //!                 }
251*fc6c6baaSBenno Lossin //!                 // We leave the scope above and gain access to the previously shadowed
252*fc6c6baaSBenno Lossin //!                 // `__InitOk` that we need to return.
253*fc6c6baaSBenno Lossin //!                 Ok(__InitOk)
254*fc6c6baaSBenno Lossin //!             });
255*fc6c6baaSBenno Lossin //!             // Change the return type of the closure.
256*fc6c6baaSBenno Lossin //!             let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> {
257*fc6c6baaSBenno Lossin //!                 init(slot).map(|__InitOk| ())
258*fc6c6baaSBenno Lossin //!             };
259*fc6c6baaSBenno Lossin //!             // Construct the initializer.
260*fc6c6baaSBenno Lossin //!             let init = unsafe {
261*fc6c6baaSBenno Lossin //!                 ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
262*fc6c6baaSBenno Lossin //!             };
263*fc6c6baaSBenno Lossin //!             init
264*fc6c6baaSBenno Lossin //!         }
265*fc6c6baaSBenno Lossin //!     }
266*fc6c6baaSBenno Lossin //! }
267*fc6c6baaSBenno Lossin //! ```
268*fc6c6baaSBenno Lossin 
269*fc6c6baaSBenno Lossin /// This macro first parses the struct definition such that it separates pinned and not pinned
270*fc6c6baaSBenno Lossin /// fields. Afterwards it declares the struct and implement the `PinData` trait safely.
271*fc6c6baaSBenno Lossin #[doc(hidden)]
272*fc6c6baaSBenno Lossin #[macro_export]
273*fc6c6baaSBenno Lossin macro_rules! __pin_data {
274*fc6c6baaSBenno Lossin     // Proc-macro entry point, this is supplied by the proc-macro pre-parsing.
275*fc6c6baaSBenno Lossin     (parse_input:
276*fc6c6baaSBenno Lossin         @args($($pinned_drop:ident)?),
277*fc6c6baaSBenno Lossin         @sig(
278*fc6c6baaSBenno Lossin             $(#[$($struct_attr:tt)*])*
279*fc6c6baaSBenno Lossin             $vis:vis struct $name:ident
280*fc6c6baaSBenno Lossin             $(where $($whr:tt)*)?
281*fc6c6baaSBenno Lossin         ),
282*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
283*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
284*fc6c6baaSBenno Lossin         @body({ $($fields:tt)* }),
285*fc6c6baaSBenno Lossin     ) => {
286*fc6c6baaSBenno Lossin         // We now use token munching to iterate through all of the fields. While doing this we
287*fc6c6baaSBenno Lossin         // identify fields marked with `#[pin]`, these fields are the 'pinned fields'. The user
288*fc6c6baaSBenno Lossin         // wants these to be structurally pinned. The rest of the fields are the
289*fc6c6baaSBenno Lossin         // 'not pinned fields'. Additionally we collect all fields, since we need them in the right
290*fc6c6baaSBenno Lossin         // order to declare the struct.
291*fc6c6baaSBenno Lossin         //
292*fc6c6baaSBenno Lossin         // In this call we also put some explaining comments for the parameters.
293*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
294*fc6c6baaSBenno Lossin             // Attributes on the struct itself, these will just be propagated to be put onto the
295*fc6c6baaSBenno Lossin             // struct definition.
296*fc6c6baaSBenno Lossin             @struct_attrs($(#[$($struct_attr)*])*),
297*fc6c6baaSBenno Lossin             // The visibility of the struct.
298*fc6c6baaSBenno Lossin             @vis($vis),
299*fc6c6baaSBenno Lossin             // The name of the struct.
300*fc6c6baaSBenno Lossin             @name($name),
301*fc6c6baaSBenno Lossin             // The 'impl generics', the generics that will need to be specified on the struct inside
302*fc6c6baaSBenno Lossin             // of an `impl<$ty_generics>` block.
303*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
304*fc6c6baaSBenno Lossin             // The 'ty generics', the generics that will need to be specified on the impl blocks.
305*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
306*fc6c6baaSBenno Lossin             // The where clause of any impl block and the declaration.
307*fc6c6baaSBenno Lossin             @where($($($whr)*)?),
308*fc6c6baaSBenno Lossin             // The remaining fields tokens that need to be processed.
309*fc6c6baaSBenno Lossin             // We add a `,` at the end to ensure correct parsing.
310*fc6c6baaSBenno Lossin             @fields_munch($($fields)* ,),
311*fc6c6baaSBenno Lossin             // The pinned fields.
312*fc6c6baaSBenno Lossin             @pinned(),
313*fc6c6baaSBenno Lossin             // The not pinned fields.
314*fc6c6baaSBenno Lossin             @not_pinned(),
315*fc6c6baaSBenno Lossin             // All fields.
316*fc6c6baaSBenno Lossin             @fields(),
317*fc6c6baaSBenno Lossin             // The accumulator containing all attributes already parsed.
318*fc6c6baaSBenno Lossin             @accum(),
319*fc6c6baaSBenno Lossin             // Contains `yes` or `` to indicate if `#[pin]` was found on the current field.
320*fc6c6baaSBenno Lossin             @is_pinned(),
321*fc6c6baaSBenno Lossin             // The proc-macro argument, this should be `PinnedDrop` or ``.
322*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
323*fc6c6baaSBenno Lossin         );
324*fc6c6baaSBenno Lossin     };
325*fc6c6baaSBenno Lossin     (find_pinned_fields:
326*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
327*fc6c6baaSBenno Lossin         @vis($vis:vis),
328*fc6c6baaSBenno Lossin         @name($name:ident),
329*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
330*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
331*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
332*fc6c6baaSBenno Lossin         // We found a PhantomPinned field, this should generally be pinned!
333*fc6c6baaSBenno Lossin         @fields_munch($field:ident : $($($(::)?core::)?marker::)?PhantomPinned, $($rest:tt)*),
334*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
335*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
336*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
337*fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
338*fc6c6baaSBenno Lossin         // This field is not pinned.
339*fc6c6baaSBenno Lossin         @is_pinned(),
340*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
341*fc6c6baaSBenno Lossin     ) => {
342*fc6c6baaSBenno Lossin         ::core::compile_error!(concat!(
343*fc6c6baaSBenno Lossin             "The field `",
344*fc6c6baaSBenno Lossin             stringify!($field),
345*fc6c6baaSBenno Lossin             "` of type `PhantomPinned` only has an effect, if it has the `#[pin]` attribute.",
346*fc6c6baaSBenno Lossin         ));
347*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
348*fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
349*fc6c6baaSBenno Lossin             @vis($vis),
350*fc6c6baaSBenno Lossin             @name($name),
351*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
352*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
353*fc6c6baaSBenno Lossin             @where($($whr)*),
354*fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
355*fc6c6baaSBenno Lossin             @pinned($($pinned)* $($accum)* $field: ::core::marker::PhantomPinned,),
356*fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
357*fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: ::core::marker::PhantomPinned,),
358*fc6c6baaSBenno Lossin             @accum(),
359*fc6c6baaSBenno Lossin             @is_pinned(),
360*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
361*fc6c6baaSBenno Lossin         );
362*fc6c6baaSBenno Lossin     };
363*fc6c6baaSBenno Lossin     (find_pinned_fields:
364*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
365*fc6c6baaSBenno Lossin         @vis($vis:vis),
366*fc6c6baaSBenno Lossin         @name($name:ident),
367*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
368*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
369*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
370*fc6c6baaSBenno Lossin         // We reached the field declaration.
371*fc6c6baaSBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
372*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
373*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
374*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
375*fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
376*fc6c6baaSBenno Lossin         // This field is pinned.
377*fc6c6baaSBenno Lossin         @is_pinned(yes),
378*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
379*fc6c6baaSBenno Lossin     ) => {
380*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
381*fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
382*fc6c6baaSBenno Lossin             @vis($vis),
383*fc6c6baaSBenno Lossin             @name($name),
384*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
385*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
386*fc6c6baaSBenno Lossin             @where($($whr)*),
387*fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
388*fc6c6baaSBenno Lossin             @pinned($($pinned)* $($accum)* $field: $type,),
389*fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
390*fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
391*fc6c6baaSBenno Lossin             @accum(),
392*fc6c6baaSBenno Lossin             @is_pinned(),
393*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
394*fc6c6baaSBenno Lossin         );
395*fc6c6baaSBenno Lossin     };
396*fc6c6baaSBenno Lossin     (find_pinned_fields:
397*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
398*fc6c6baaSBenno Lossin         @vis($vis:vis),
399*fc6c6baaSBenno Lossin         @name($name:ident),
400*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
401*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
402*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
403*fc6c6baaSBenno Lossin         // We reached the field declaration.
404*fc6c6baaSBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
405*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
406*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
407*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
408*fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
409*fc6c6baaSBenno Lossin         // This field is not pinned.
410*fc6c6baaSBenno Lossin         @is_pinned(),
411*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
412*fc6c6baaSBenno Lossin     ) => {
413*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
414*fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
415*fc6c6baaSBenno Lossin             @vis($vis),
416*fc6c6baaSBenno Lossin             @name($name),
417*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
418*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
419*fc6c6baaSBenno Lossin             @where($($whr)*),
420*fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
421*fc6c6baaSBenno Lossin             @pinned($($pinned)*),
422*fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)* $($accum)* $field: $type,),
423*fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
424*fc6c6baaSBenno Lossin             @accum(),
425*fc6c6baaSBenno Lossin             @is_pinned(),
426*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
427*fc6c6baaSBenno Lossin         );
428*fc6c6baaSBenno Lossin     };
429*fc6c6baaSBenno Lossin     (find_pinned_fields:
430*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
431*fc6c6baaSBenno Lossin         @vis($vis:vis),
432*fc6c6baaSBenno Lossin         @name($name:ident),
433*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
434*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
435*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
436*fc6c6baaSBenno Lossin         // We found the `#[pin]` attr.
437*fc6c6baaSBenno Lossin         @fields_munch(#[pin] $($rest:tt)*),
438*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
439*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
440*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
441*fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
442*fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
443*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
444*fc6c6baaSBenno Lossin     ) => {
445*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
446*fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
447*fc6c6baaSBenno Lossin             @vis($vis),
448*fc6c6baaSBenno Lossin             @name($name),
449*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
450*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
451*fc6c6baaSBenno Lossin             @where($($whr)*),
452*fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
453*fc6c6baaSBenno Lossin             // We do not include `#[pin]` in the list of attributes, since it is not actually an
454*fc6c6baaSBenno Lossin             // attribute that is defined somewhere.
455*fc6c6baaSBenno Lossin             @pinned($($pinned)*),
456*fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
457*fc6c6baaSBenno Lossin             @fields($($fields)*),
458*fc6c6baaSBenno Lossin             @accum($($accum)*),
459*fc6c6baaSBenno Lossin             // Set this to `yes`.
460*fc6c6baaSBenno Lossin             @is_pinned(yes),
461*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
462*fc6c6baaSBenno Lossin         );
463*fc6c6baaSBenno Lossin     };
464*fc6c6baaSBenno Lossin     (find_pinned_fields:
465*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
466*fc6c6baaSBenno Lossin         @vis($vis:vis),
467*fc6c6baaSBenno Lossin         @name($name:ident),
468*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
469*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
470*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
471*fc6c6baaSBenno Lossin         // We reached the field declaration with visibility, for simplicity we only munch the
472*fc6c6baaSBenno Lossin         // visibility and put it into `$accum`.
473*fc6c6baaSBenno Lossin         @fields_munch($fvis:vis $field:ident $($rest:tt)*),
474*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
475*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
476*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
477*fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
478*fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
479*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
480*fc6c6baaSBenno Lossin     ) => {
481*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
482*fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
483*fc6c6baaSBenno Lossin             @vis($vis),
484*fc6c6baaSBenno Lossin             @name($name),
485*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
486*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
487*fc6c6baaSBenno Lossin             @where($($whr)*),
488*fc6c6baaSBenno Lossin             @fields_munch($field $($rest)*),
489*fc6c6baaSBenno Lossin             @pinned($($pinned)*),
490*fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
491*fc6c6baaSBenno Lossin             @fields($($fields)*),
492*fc6c6baaSBenno Lossin             @accum($($accum)* $fvis),
493*fc6c6baaSBenno Lossin             @is_pinned($($is_pinned)?),
494*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
495*fc6c6baaSBenno Lossin         );
496*fc6c6baaSBenno Lossin     };
497*fc6c6baaSBenno Lossin     (find_pinned_fields:
498*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
499*fc6c6baaSBenno Lossin         @vis($vis:vis),
500*fc6c6baaSBenno Lossin         @name($name:ident),
501*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
502*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
503*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
504*fc6c6baaSBenno Lossin         // Some other attribute, just put it into `$accum`.
505*fc6c6baaSBenno Lossin         @fields_munch(#[$($attr:tt)*] $($rest:tt)*),
506*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
507*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
508*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
509*fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
510*fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
511*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
512*fc6c6baaSBenno Lossin     ) => {
513*fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
514*fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
515*fc6c6baaSBenno Lossin             @vis($vis),
516*fc6c6baaSBenno Lossin             @name($name),
517*fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
518*fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
519*fc6c6baaSBenno Lossin             @where($($whr)*),
520*fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
521*fc6c6baaSBenno Lossin             @pinned($($pinned)*),
522*fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
523*fc6c6baaSBenno Lossin             @fields($($fields)*),
524*fc6c6baaSBenno Lossin             @accum($($accum)* #[$($attr)*]),
525*fc6c6baaSBenno Lossin             @is_pinned($($is_pinned)?),
526*fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
527*fc6c6baaSBenno Lossin         );
528*fc6c6baaSBenno Lossin     };
529*fc6c6baaSBenno Lossin     (find_pinned_fields:
530*fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
531*fc6c6baaSBenno Lossin         @vis($vis:vis),
532*fc6c6baaSBenno Lossin         @name($name:ident),
533*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
534*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
535*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
536*fc6c6baaSBenno Lossin         // We reached the end of the fields, plus an optional additional comma, since we added one
537*fc6c6baaSBenno Lossin         // before and the user is also allowed to put a trailing comma.
538*fc6c6baaSBenno Lossin         @fields_munch($(,)?),
539*fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
540*fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
541*fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
542*fc6c6baaSBenno Lossin         @accum(),
543*fc6c6baaSBenno Lossin         @is_pinned(),
544*fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
545*fc6c6baaSBenno Lossin     ) => {
546*fc6c6baaSBenno Lossin         // Declare the struct with all fields in the correct order.
547*fc6c6baaSBenno Lossin         $($struct_attrs)*
548*fc6c6baaSBenno Lossin         $vis struct $name <$($impl_generics)*>
549*fc6c6baaSBenno Lossin         where $($whr)*
550*fc6c6baaSBenno Lossin         {
551*fc6c6baaSBenno Lossin             $($fields)*
552*fc6c6baaSBenno Lossin         }
553*fc6c6baaSBenno Lossin 
554*fc6c6baaSBenno Lossin         // We put the rest into this const item, because it then will not be accessible to anything
555*fc6c6baaSBenno Lossin         // outside.
556*fc6c6baaSBenno Lossin         const _: () = {
557*fc6c6baaSBenno Lossin             // We declare this struct which will host all of the projection function for our type.
558*fc6c6baaSBenno Lossin             // it will be invariant over all generic parameters which are inherited from the
559*fc6c6baaSBenno Lossin             // struct.
560*fc6c6baaSBenno Lossin             $vis struct __ThePinData<$($impl_generics)*>
561*fc6c6baaSBenno Lossin             where $($whr)*
562*fc6c6baaSBenno Lossin             {
563*fc6c6baaSBenno Lossin                 __phantom: ::core::marker::PhantomData<
564*fc6c6baaSBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
565*fc6c6baaSBenno Lossin                 >,
566*fc6c6baaSBenno Lossin             }
567*fc6c6baaSBenno Lossin 
568*fc6c6baaSBenno Lossin             impl<$($impl_generics)*> ::core::clone::Clone for __ThePinData<$($ty_generics)*>
569*fc6c6baaSBenno Lossin             where $($whr)*
570*fc6c6baaSBenno Lossin             {
571*fc6c6baaSBenno Lossin                 fn clone(&self) -> Self { *self }
572*fc6c6baaSBenno Lossin             }
573*fc6c6baaSBenno Lossin 
574*fc6c6baaSBenno Lossin             impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*>
575*fc6c6baaSBenno Lossin             where $($whr)*
576*fc6c6baaSBenno Lossin             {}
577*fc6c6baaSBenno Lossin 
578*fc6c6baaSBenno Lossin             // Make all projection functions.
579*fc6c6baaSBenno Lossin             $crate::__pin_data!(make_pin_data:
580*fc6c6baaSBenno Lossin                 @pin_data(__ThePinData),
581*fc6c6baaSBenno Lossin                 @impl_generics($($impl_generics)*),
582*fc6c6baaSBenno Lossin                 @ty_generics($($ty_generics)*),
583*fc6c6baaSBenno Lossin                 @where($($whr)*),
584*fc6c6baaSBenno Lossin                 @pinned($($pinned)*),
585*fc6c6baaSBenno Lossin                 @not_pinned($($not_pinned)*),
586*fc6c6baaSBenno Lossin             );
587*fc6c6baaSBenno Lossin 
588*fc6c6baaSBenno Lossin             // SAFETY: We have added the correct projection functions above to `__ThePinData` and
589*fc6c6baaSBenno Lossin             // we also use the least restrictive generics possible.
590*fc6c6baaSBenno Lossin             unsafe impl<$($impl_generics)*>
591*fc6c6baaSBenno Lossin                 $crate::init::__internal::HasPinData for $name<$($ty_generics)*>
592*fc6c6baaSBenno Lossin             where $($whr)*
593*fc6c6baaSBenno Lossin             {
594*fc6c6baaSBenno Lossin                 type PinData = __ThePinData<$($ty_generics)*>;
595*fc6c6baaSBenno Lossin 
596*fc6c6baaSBenno Lossin                 unsafe fn __pin_data() -> Self::PinData {
597*fc6c6baaSBenno Lossin                     __ThePinData { __phantom: ::core::marker::PhantomData }
598*fc6c6baaSBenno Lossin                 }
599*fc6c6baaSBenno Lossin             }
600*fc6c6baaSBenno Lossin 
601*fc6c6baaSBenno Lossin             unsafe impl<$($impl_generics)*>
602*fc6c6baaSBenno Lossin                 $crate::init::__internal::PinData for __ThePinData<$($ty_generics)*>
603*fc6c6baaSBenno Lossin             where $($whr)*
604*fc6c6baaSBenno Lossin             {
605*fc6c6baaSBenno Lossin                 type Datee = $name<$($ty_generics)*>;
606*fc6c6baaSBenno Lossin             }
607*fc6c6baaSBenno Lossin 
608*fc6c6baaSBenno Lossin             // This struct will be used for the unpin analysis. Since only structurally pinned
609*fc6c6baaSBenno Lossin             // fields are relevant whether the struct should implement `Unpin`.
610*fc6c6baaSBenno Lossin             #[allow(dead_code)]
611*fc6c6baaSBenno Lossin             struct __Unpin <'__pin, $($impl_generics)*>
612*fc6c6baaSBenno Lossin             where $($whr)*
613*fc6c6baaSBenno Lossin             {
614*fc6c6baaSBenno Lossin                 __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
615*fc6c6baaSBenno Lossin                 __phantom: ::core::marker::PhantomData<
616*fc6c6baaSBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
617*fc6c6baaSBenno Lossin                 >,
618*fc6c6baaSBenno Lossin                 // Only the pinned fields.
619*fc6c6baaSBenno Lossin                 $($pinned)*
620*fc6c6baaSBenno Lossin             }
621*fc6c6baaSBenno Lossin 
622*fc6c6baaSBenno Lossin             #[doc(hidden)]
623*fc6c6baaSBenno Lossin             impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*>
624*fc6c6baaSBenno Lossin             where
625*fc6c6baaSBenno Lossin                 __Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin,
626*fc6c6baaSBenno Lossin                 $($whr)*
627*fc6c6baaSBenno Lossin             {}
628*fc6c6baaSBenno Lossin 
629*fc6c6baaSBenno Lossin             // We need to disallow normal `Drop` implementation, the exact behavior depends on
630*fc6c6baaSBenno Lossin             // whether `PinnedDrop` was specified as the parameter.
631*fc6c6baaSBenno Lossin             $crate::__pin_data!(drop_prevention:
632*fc6c6baaSBenno Lossin                 @name($name),
633*fc6c6baaSBenno Lossin                 @impl_generics($($impl_generics)*),
634*fc6c6baaSBenno Lossin                 @ty_generics($($ty_generics)*),
635*fc6c6baaSBenno Lossin                 @where($($whr)*),
636*fc6c6baaSBenno Lossin                 @pinned_drop($($pinned_drop)?),
637*fc6c6baaSBenno Lossin             );
638*fc6c6baaSBenno Lossin         };
639*fc6c6baaSBenno Lossin     };
640*fc6c6baaSBenno Lossin     // When no `PinnedDrop` was specified, then we have to prevent implementing drop.
641*fc6c6baaSBenno Lossin     (drop_prevention:
642*fc6c6baaSBenno Lossin         @name($name:ident),
643*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
644*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
645*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
646*fc6c6baaSBenno Lossin         @pinned_drop(),
647*fc6c6baaSBenno Lossin     ) => {
648*fc6c6baaSBenno Lossin         // We prevent this by creating a trait that will be implemented for all types implementing
649*fc6c6baaSBenno Lossin         // `Drop`. Additionally we will implement this trait for the struct leading to a conflict,
650*fc6c6baaSBenno Lossin         // if it also implements `Drop`
651*fc6c6baaSBenno Lossin         trait MustNotImplDrop {}
652*fc6c6baaSBenno Lossin         #[allow(drop_bounds)]
653*fc6c6baaSBenno Lossin         impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
654*fc6c6baaSBenno Lossin         impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*>
655*fc6c6baaSBenno Lossin         where $($whr)* {}
656*fc6c6baaSBenno Lossin     };
657*fc6c6baaSBenno Lossin     // If some other parameter was specified, we emit a readable error.
658*fc6c6baaSBenno Lossin     (drop_prevention:
659*fc6c6baaSBenno Lossin         @name($name:ident),
660*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
661*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
662*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
663*fc6c6baaSBenno Lossin         @pinned_drop($($rest:tt)*),
664*fc6c6baaSBenno Lossin     ) => {
665*fc6c6baaSBenno Lossin         compile_error!(
666*fc6c6baaSBenno Lossin             "Wrong parameters to `#[pin_data]`, expected nothing or `PinnedDrop`, got '{}'.",
667*fc6c6baaSBenno Lossin             stringify!($($rest)*),
668*fc6c6baaSBenno Lossin         );
669*fc6c6baaSBenno Lossin     };
670*fc6c6baaSBenno Lossin     (make_pin_data:
671*fc6c6baaSBenno Lossin         @pin_data($pin_data:ident),
672*fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
673*fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
674*fc6c6baaSBenno Lossin         @where($($whr:tt)*),
675*fc6c6baaSBenno Lossin         @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
676*fc6c6baaSBenno Lossin         @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
677*fc6c6baaSBenno Lossin     ) => {
678*fc6c6baaSBenno Lossin         // For every field, we create a projection function according to its projection type. If a
679*fc6c6baaSBenno Lossin         // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
680*fc6c6baaSBenno Lossin         // structurally pinned, then it can be initialized via `Init`.
681*fc6c6baaSBenno Lossin         //
682*fc6c6baaSBenno Lossin         // The functions are `unsafe` to prevent accidentally calling them.
683*fc6c6baaSBenno Lossin         #[allow(dead_code)]
684*fc6c6baaSBenno Lossin         impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
685*fc6c6baaSBenno Lossin         where $($whr)*
686*fc6c6baaSBenno Lossin         {
687*fc6c6baaSBenno Lossin             $(
688*fc6c6baaSBenno Lossin                 $pvis unsafe fn $p_field<E>(
689*fc6c6baaSBenno Lossin                     self,
690*fc6c6baaSBenno Lossin                     slot: *mut $p_type,
691*fc6c6baaSBenno Lossin                     init: impl $crate::init::PinInit<$p_type, E>,
692*fc6c6baaSBenno Lossin                 ) -> ::core::result::Result<(), E> {
693*fc6c6baaSBenno Lossin                     unsafe { $crate::init::PinInit::__pinned_init(init, slot) }
694*fc6c6baaSBenno Lossin                 }
695*fc6c6baaSBenno Lossin             )*
696*fc6c6baaSBenno Lossin             $(
697*fc6c6baaSBenno Lossin                 $fvis unsafe fn $field<E>(
698*fc6c6baaSBenno Lossin                     self,
699*fc6c6baaSBenno Lossin                     slot: *mut $type,
700*fc6c6baaSBenno Lossin                     init: impl $crate::init::Init<$type, E>,
701*fc6c6baaSBenno Lossin                 ) -> ::core::result::Result<(), E> {
702*fc6c6baaSBenno Lossin                     unsafe { $crate::init::Init::__init(init, slot) }
703*fc6c6baaSBenno Lossin                 }
704*fc6c6baaSBenno Lossin             )*
705*fc6c6baaSBenno Lossin         }
706*fc6c6baaSBenno Lossin     };
707*fc6c6baaSBenno Lossin }
708