xref: /openbmc/linux/rust/kernel/init/macros.rs (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1fc6c6baaSBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
2fc6c6baaSBenno Lossin 
3fc6c6baaSBenno Lossin //! This module provides the macros that actually implement the proc-macros `pin_data` and
4b3068ac3SBenno Lossin //! `pinned_drop`. It also contains `__init_internal` the implementation of the `{try_}{pin_}init!`
5b3068ac3SBenno Lossin //! macros.
6fc6c6baaSBenno Lossin //!
7fc6c6baaSBenno Lossin //! These macros should never be called directly, since they expect their input to be
8b3068ac3SBenno Lossin //! in a certain format which is internal. If used incorrectly, these macros can lead to UB even in
9b3068ac3SBenno Lossin //! safe code! Use the public facing macros instead.
10fc6c6baaSBenno Lossin //!
11fc6c6baaSBenno Lossin //! This architecture has been chosen because the kernel does not yet have access to `syn` which
12fc6c6baaSBenno Lossin //! would make matters a lot easier for implementing these as proc-macros.
13fc6c6baaSBenno Lossin //!
14fc6c6baaSBenno Lossin //! # Macro expansion example
15fc6c6baaSBenno Lossin //!
16fc6c6baaSBenno Lossin //! This section is intended for readers trying to understand the macros in this module and the
17fc6c6baaSBenno Lossin //! `pin_init!` macros from `init.rs`.
18fc6c6baaSBenno Lossin //!
19fc6c6baaSBenno Lossin //! We will look at the following example:
20fc6c6baaSBenno Lossin //!
21309786c2SBenno Lossin //! ```rust,ignore
22fc6c6baaSBenno Lossin //! # use kernel::init::*;
23309786c2SBenno Lossin //! # use core::pin::Pin;
24fc6c6baaSBenno Lossin //! #[pin_data]
25fc6c6baaSBenno Lossin //! #[repr(C)]
26fc6c6baaSBenno Lossin //! struct Bar<T> {
27fc6c6baaSBenno Lossin //!     #[pin]
28fc6c6baaSBenno Lossin //!     t: T,
29fc6c6baaSBenno Lossin //!     pub x: usize,
30fc6c6baaSBenno Lossin //! }
31fc6c6baaSBenno Lossin //!
32fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
33fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
34fc6c6baaSBenno Lossin //!         pin_init!(Self { t, x: 0 })
35fc6c6baaSBenno Lossin //!     }
36fc6c6baaSBenno Lossin //! }
37d0fdc396SBenno Lossin //!
38d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)]
39d0fdc396SBenno Lossin //! struct Foo {
40d0fdc396SBenno Lossin //!     a: usize,
41d0fdc396SBenno Lossin //!     #[pin]
42d0fdc396SBenno Lossin //!     b: Bar<u32>,
43d0fdc396SBenno Lossin //! }
44d0fdc396SBenno Lossin //!
45d0fdc396SBenno Lossin //! #[pinned_drop]
46d0fdc396SBenno Lossin //! impl PinnedDrop for Foo {
47d0fdc396SBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
48*4af84c6aSBenno Lossin //!         pr_info!("{self:p} is getting dropped.");
49d0fdc396SBenno Lossin //!     }
50d0fdc396SBenno Lossin //! }
51d0fdc396SBenno Lossin //!
52d0fdc396SBenno Lossin //! let a = 42;
53d0fdc396SBenno Lossin //! let initializer = pin_init!(Foo {
54d0fdc396SBenno Lossin //!     a,
55d0fdc396SBenno Lossin //!     b <- Bar::new(36),
56d0fdc396SBenno Lossin //! });
57fc6c6baaSBenno Lossin //! ```
58fc6c6baaSBenno Lossin //!
59fc6c6baaSBenno Lossin //! This example includes the most common and important features of the pin-init API.
60fc6c6baaSBenno Lossin //!
61fc6c6baaSBenno Lossin //! Below you can find individual section about the different macro invocations. Here are some
62fc6c6baaSBenno Lossin //! general things we need to take into account when designing macros:
63fc6c6baaSBenno Lossin //! - use global paths, similarly to file paths, these start with the separator: `::core::panic!()`
64fc6c6baaSBenno Lossin //!   this ensures that the correct item is used, since users could define their own `mod core {}`
65fc6c6baaSBenno Lossin //!   and then their own `panic!` inside to execute arbitrary code inside of our macro.
66fc6c6baaSBenno Lossin //! - macro `unsafe` hygiene: we need to ensure that we do not expand arbitrary, user-supplied
67fc6c6baaSBenno Lossin //!   expressions inside of an `unsafe` block in the macro, because this would allow users to do
68fc6c6baaSBenno Lossin //!   `unsafe` operations without an associated `unsafe` block.
69fc6c6baaSBenno Lossin //!
70fc6c6baaSBenno Lossin //! ## `#[pin_data]` on `Bar`
71fc6c6baaSBenno Lossin //!
72fc6c6baaSBenno Lossin //! This macro is used to specify which fields are structurally pinned and which fields are not. It
73fc6c6baaSBenno Lossin //! is placed on the struct definition and allows `#[pin]` to be placed on the fields.
74fc6c6baaSBenno Lossin //!
75fc6c6baaSBenno Lossin //! Here is the definition of `Bar` from our example:
76fc6c6baaSBenno Lossin //!
77309786c2SBenno Lossin //! ```rust,ignore
78fc6c6baaSBenno Lossin //! # use kernel::init::*;
79fc6c6baaSBenno Lossin //! #[pin_data]
80fc6c6baaSBenno Lossin //! #[repr(C)]
81fc6c6baaSBenno Lossin //! struct Bar<T> {
82309786c2SBenno Lossin //!     #[pin]
83fc6c6baaSBenno Lossin //!     t: T,
84fc6c6baaSBenno Lossin //!     pub x: usize,
85fc6c6baaSBenno Lossin //! }
86fc6c6baaSBenno Lossin //! ```
87fc6c6baaSBenno Lossin //!
88fc6c6baaSBenno Lossin //! This expands to the following code:
89fc6c6baaSBenno Lossin //!
90309786c2SBenno Lossin //! ```rust,ignore
91fc6c6baaSBenno Lossin //! // Firstly the normal definition of the struct, attributes are preserved:
92fc6c6baaSBenno Lossin //! #[repr(C)]
93fc6c6baaSBenno Lossin //! struct Bar<T> {
94fc6c6baaSBenno Lossin //!     t: T,
95fc6c6baaSBenno Lossin //!     pub x: usize,
96fc6c6baaSBenno Lossin //! }
97fc6c6baaSBenno Lossin //! // Then an anonymous constant is defined, this is because we do not want any code to access the
98fc6c6baaSBenno Lossin //! // types that we define inside:
99fc6c6baaSBenno Lossin //! const _: () = {
100fc6c6baaSBenno Lossin //!     // We define the pin-data carrying struct, it is a ZST and needs to have the same generics,
101fc6c6baaSBenno Lossin //!     // since we need to implement access functions for each field and thus need to know its
102fc6c6baaSBenno Lossin //!     // type.
103fc6c6baaSBenno Lossin //!     struct __ThePinData<T> {
104fc6c6baaSBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
105fc6c6baaSBenno Lossin //!     }
106fc6c6baaSBenno Lossin //!     // We implement `Copy` for the pin-data struct, since all functions it defines will take
107fc6c6baaSBenno Lossin //!     // `self` by value.
108fc6c6baaSBenno Lossin //!     impl<T> ::core::clone::Clone for __ThePinData<T> {
109fc6c6baaSBenno Lossin //!         fn clone(&self) -> Self {
110fc6c6baaSBenno Lossin //!             *self
111fc6c6baaSBenno Lossin //!         }
112fc6c6baaSBenno Lossin //!     }
113fc6c6baaSBenno Lossin //!     impl<T> ::core::marker::Copy for __ThePinData<T> {}
114fc6c6baaSBenno Lossin //!     // For every field of `Bar`, the pin-data struct will define a function with the same name
115fc6c6baaSBenno Lossin //!     // and accessor (`pub` or `pub(crate)` etc.). This function will take a pointer to the
116fc6c6baaSBenno Lossin //!     // field (`slot`) and a `PinInit` or `Init` depending on the projection kind of the field
117fc6c6baaSBenno Lossin //!     // (if pinning is structural for the field, then `PinInit` otherwise `Init`).
118fc6c6baaSBenno Lossin //!     #[allow(dead_code)]
119fc6c6baaSBenno Lossin //!     impl<T> __ThePinData<T> {
120fc6c6baaSBenno Lossin //!         unsafe fn t<E>(
121fc6c6baaSBenno Lossin //!             self,
122fc6c6baaSBenno Lossin //!             slot: *mut T,
123309786c2SBenno Lossin //!             // Since `t` is `#[pin]`, this is `PinInit`.
124309786c2SBenno Lossin //!             init: impl ::kernel::init::PinInit<T, E>,
125fc6c6baaSBenno Lossin //!         ) -> ::core::result::Result<(), E> {
126309786c2SBenno Lossin //!             unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
127fc6c6baaSBenno Lossin //!         }
128fc6c6baaSBenno Lossin //!         pub unsafe fn x<E>(
129fc6c6baaSBenno Lossin //!             self,
130fc6c6baaSBenno Lossin //!             slot: *mut usize,
131309786c2SBenno Lossin //!             // Since `x` is not `#[pin]`, this is `Init`.
132fc6c6baaSBenno Lossin //!             init: impl ::kernel::init::Init<usize, E>,
133fc6c6baaSBenno Lossin //!         ) -> ::core::result::Result<(), E> {
134fc6c6baaSBenno Lossin //!             unsafe { ::kernel::init::Init::__init(init, slot) }
135fc6c6baaSBenno Lossin //!         }
136fc6c6baaSBenno Lossin //!     }
137fc6c6baaSBenno Lossin //!     // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct
138309786c2SBenno Lossin //!     // that we constructed above.
139fc6c6baaSBenno Lossin //!     unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> {
140fc6c6baaSBenno Lossin //!         type PinData = __ThePinData<T>;
141fc6c6baaSBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
142fc6c6baaSBenno Lossin //!             __ThePinData {
143fc6c6baaSBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
144fc6c6baaSBenno Lossin //!             }
145fc6c6baaSBenno Lossin //!         }
146fc6c6baaSBenno Lossin //!     }
147fc6c6baaSBenno Lossin //!     // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data
148fc6c6baaSBenno Lossin //!     // struct. This is important to ensure that no user can implement a rouge `__pin_data`
149fc6c6baaSBenno Lossin //!     // function without using `unsafe`.
150fc6c6baaSBenno Lossin //!     unsafe impl<T> ::kernel::init::__internal::PinData for __ThePinData<T> {
151fc6c6baaSBenno Lossin //!         type Datee = Bar<T>;
152fc6c6baaSBenno Lossin //!     }
153fc6c6baaSBenno Lossin //!     // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is
154fc6c6baaSBenno Lossin //!     // `Unpin`. In other words, whether `Bar` is `Unpin` only depends on structurally pinned
155fc6c6baaSBenno Lossin //!     // fields (those marked with `#[pin]`). These fields will be listed in this struct, in our
156fc6c6baaSBenno Lossin //!     // case no such fields exist, hence this is almost empty. The two phantomdata fields exist
157fc6c6baaSBenno Lossin //!     // for two reasons:
158fc6c6baaSBenno Lossin //!     // - `__phantom`: every generic must be used, since we cannot really know which generics
159fc6c6baaSBenno Lossin //!     //   are used, we declere all and then use everything here once.
160fc6c6baaSBenno Lossin //!     // - `__phantom_pin`: uses the `'__pin` lifetime and ensures that this struct is invariant
161fc6c6baaSBenno Lossin //!     //   over it. The lifetime is needed to work around the limitation that trait bounds must
162fc6c6baaSBenno Lossin //!     //   not be trivial, e.g. the user has a `#[pin] PhantomPinned` field -- this is
163fc6c6baaSBenno Lossin //!     //   unconditionally `!Unpin` and results in an error. The lifetime tricks the compiler
164fc6c6baaSBenno Lossin //!     //   into accepting these bounds regardless.
165fc6c6baaSBenno Lossin //!     #[allow(dead_code)]
166fc6c6baaSBenno Lossin //!     struct __Unpin<'__pin, T> {
167fc6c6baaSBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
168fc6c6baaSBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
169309786c2SBenno Lossin //!         // Our only `#[pin]` field is `t`.
170309786c2SBenno Lossin //!         t: T,
171fc6c6baaSBenno Lossin //!     }
172fc6c6baaSBenno Lossin //!     #[doc(hidden)]
173*4af84c6aSBenno Lossin //!     impl<'__pin, T> ::core::marker::Unpin for Bar<T>
174*4af84c6aSBenno Lossin //!     where
175*4af84c6aSBenno Lossin //!         __Unpin<'__pin, T>: ::core::marker::Unpin,
176*4af84c6aSBenno Lossin //!     {}
177fc6c6baaSBenno Lossin //!     // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
178fc6c6baaSBenno Lossin //!     // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
179fc6c6baaSBenno Lossin //!     // UB with only safe code, so we disallow this by giving a trait implementation error using
180fc6c6baaSBenno Lossin //!     // a direct impl and a blanket implementation.
181fc6c6baaSBenno Lossin //!     trait MustNotImplDrop {}
182fc6c6baaSBenno Lossin //!     // Normally `Drop` bounds do not have the correct semantics, but for this purpose they do
183fc6c6baaSBenno Lossin //!     // (normally people want to know if a type has any kind of drop glue at all, here we want
184fc6c6baaSBenno Lossin //!     // to know if it has any kind of custom drop glue, which is exactly what this bound does).
185fc6c6baaSBenno Lossin //!     #[allow(drop_bounds)]
186fc6c6baaSBenno Lossin //!     impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
187fc6c6baaSBenno Lossin //!     impl<T> MustNotImplDrop for Bar<T> {}
188d0fdc396SBenno Lossin //!     // Here comes a convenience check, if one implemented `PinnedDrop`, but forgot to add it to
189d0fdc396SBenno Lossin //!     // `#[pin_data]`, then this will error with the same mechanic as above, this is not needed
190d0fdc396SBenno Lossin //!     // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`.
191d0fdc396SBenno Lossin //!     #[allow(non_camel_case_types)]
192d0fdc396SBenno Lossin //!     trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
193*4af84c6aSBenno Lossin //!     impl<
194*4af84c6aSBenno Lossin //!         T: ::kernel::init::PinnedDrop,
195*4af84c6aSBenno Lossin //!     > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
196d0fdc396SBenno Lossin //!     impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
197fc6c6baaSBenno Lossin //! };
198fc6c6baaSBenno Lossin //! ```
199fc6c6baaSBenno Lossin //!
200fc6c6baaSBenno Lossin //! ## `pin_init!` in `impl Bar`
201fc6c6baaSBenno Lossin //!
202fc6c6baaSBenno Lossin //! This macro creates an pin-initializer for the given struct. It requires that the struct is
203fc6c6baaSBenno Lossin //! annotated by `#[pin_data]`.
204fc6c6baaSBenno Lossin //!
205fc6c6baaSBenno Lossin //! Here is the impl on `Bar` defining the new function:
206fc6c6baaSBenno Lossin //!
207309786c2SBenno Lossin //! ```rust,ignore
208fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
209fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
210fc6c6baaSBenno Lossin //!         pin_init!(Self { t, x: 0 })
211fc6c6baaSBenno Lossin //!     }
212fc6c6baaSBenno Lossin //! }
213fc6c6baaSBenno Lossin //! ```
214fc6c6baaSBenno Lossin //!
215fc6c6baaSBenno Lossin //! This expands to the following code:
216fc6c6baaSBenno Lossin //!
217309786c2SBenno Lossin //! ```rust,ignore
218fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
219fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
220fc6c6baaSBenno Lossin //!         {
221fc6c6baaSBenno Lossin //!             // We do not want to allow arbitrary returns, so we declare this type as the `Ok`
222fc6c6baaSBenno Lossin //!             // return type and shadow it later when we insert the arbitrary user code. That way
223fc6c6baaSBenno Lossin //!             // there will be no possibility of returning without `unsafe`.
224fc6c6baaSBenno Lossin //!             struct __InitOk;
225*4af84c6aSBenno Lossin //!             // Get the data about fields from the supplied type.
226fc6c6baaSBenno Lossin //!             // - the function is unsafe, hence the unsafe block
227fc6c6baaSBenno Lossin //!             // - we `use` the `HasPinData` trait in the block, it is only available in that
228fc6c6baaSBenno Lossin //!             //   scope.
229fc6c6baaSBenno Lossin //!             let data = unsafe {
230fc6c6baaSBenno Lossin //!                 use ::kernel::init::__internal::HasPinData;
231fc6c6baaSBenno Lossin //!                 Self::__pin_data()
232fc6c6baaSBenno Lossin //!             };
233*4af84c6aSBenno Lossin //!             // Ensure that `data` really is of type `PinData` and help with type inference:
234fc6c6baaSBenno Lossin //!             let init = ::kernel::init::__internal::PinData::make_closure::<
235fc6c6baaSBenno Lossin //!                 _,
236fc6c6baaSBenno Lossin //!                 __InitOk,
237fc6c6baaSBenno Lossin //!                 ::core::convert::Infallible,
238fc6c6baaSBenno Lossin //!             >(data, move |slot| {
239fc6c6baaSBenno Lossin //!                 {
240fc6c6baaSBenno Lossin //!                     // Shadow the structure so it cannot be used to return early. If a user
241*4af84c6aSBenno Lossin //!                     // tries to write `return Ok(__InitOk)`, then they get a type error,
242*4af84c6aSBenno Lossin //!                     // since that will refer to this struct instead of the one defined
243*4af84c6aSBenno Lossin //!                     // above.
244fc6c6baaSBenno Lossin //!                     struct __InitOk;
245fc6c6baaSBenno Lossin //!                     // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
246*4af84c6aSBenno Lossin //!                     {
247309786c2SBenno Lossin //!                         unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) };
248*4af84c6aSBenno Lossin //!                     }
249*4af84c6aSBenno Lossin //!                     // Since initialization could fail later (not in this case, since the
250*4af84c6aSBenno Lossin //!                     // error type is `Infallible`) we will need to drop this field if there
251*4af84c6aSBenno Lossin //!                     // is an error later. This `DropGuard` will drop the field when it gets
252*4af84c6aSBenno Lossin //!                     // dropped and has not yet been forgotten.
253*4af84c6aSBenno Lossin //!                     let t = unsafe {
254*4af84c6aSBenno Lossin //!                         ::pinned_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
255fc6c6baaSBenno Lossin //!                     };
256fc6c6baaSBenno Lossin //!                     // Expansion of `x: 0,`:
257*4af84c6aSBenno Lossin //!                     // Since this can be an arbitrary expression we cannot place it inside
258*4af84c6aSBenno Lossin //!                     // of the `unsafe` block, so we bind it here.
259*4af84c6aSBenno Lossin //!                     {
260fc6c6baaSBenno Lossin //!                         let x = 0;
261309786c2SBenno Lossin //!                         unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
262*4af84c6aSBenno Lossin //!                     }
263309786c2SBenno Lossin //!                     // We again create a `DropGuard`.
264*4af84c6aSBenno Lossin //!                     let x = unsafe {
265*4af84c6aSBenno Lossin //!                         ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
266fc6c6baaSBenno Lossin //!                     };
267*4af84c6aSBenno Lossin //!                     // Since initialization has successfully completed, we can now forget
268*4af84c6aSBenno Lossin //!                     // the guards. This is not `mem::forget`, since we only have
269*4af84c6aSBenno Lossin //!                     // `&DropGuard`.
270*4af84c6aSBenno Lossin //!                     ::core::mem::forget(x);
271*4af84c6aSBenno Lossin //!                     ::core::mem::forget(t);
272309786c2SBenno Lossin //!                     // Here we use the type checker to ensure that every field has been
273fc6c6baaSBenno Lossin //!                     // initialized exactly once, since this is `if false` it will never get
274fc6c6baaSBenno Lossin //!                     // executed, but still type-checked.
275*4af84c6aSBenno Lossin //!                     // Additionally we abuse `slot` to automatically infer the correct type
276*4af84c6aSBenno Lossin //!                     // for the struct. This is also another check that every field is
277*4af84c6aSBenno Lossin //!                     // accessible from this scope.
278fc6c6baaSBenno Lossin //!                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
279*4af84c6aSBenno Lossin //!                     let _ = || {
280fc6c6baaSBenno Lossin //!                         unsafe {
281fc6c6baaSBenno Lossin //!                             ::core::ptr::write(
282fc6c6baaSBenno Lossin //!                                 slot,
283fc6c6baaSBenno Lossin //!                                 Self {
284*4af84c6aSBenno Lossin //!                                     // We only care about typecheck finding every field
285*4af84c6aSBenno Lossin //!                                     // here, the expression does not matter, just conjure
286*4af84c6aSBenno Lossin //!                                     // one using `panic!()`:
287fc6c6baaSBenno Lossin //!                                     t: ::core::panic!(),
288fc6c6baaSBenno Lossin //!                                     x: ::core::panic!(),
289fc6c6baaSBenno Lossin //!                                 },
290fc6c6baaSBenno Lossin //!                             );
291fc6c6baaSBenno Lossin //!                         };
292*4af84c6aSBenno Lossin //!                     };
293fc6c6baaSBenno Lossin //!                 }
294fc6c6baaSBenno Lossin //!                 // We leave the scope above and gain access to the previously shadowed
295fc6c6baaSBenno Lossin //!                 // `__InitOk` that we need to return.
296fc6c6baaSBenno Lossin //!                 Ok(__InitOk)
297fc6c6baaSBenno Lossin //!             });
298309786c2SBenno Lossin //!             // Change the return type from `__InitOk` to `()`.
299*4af84c6aSBenno Lossin //!             let init = move |
300*4af84c6aSBenno Lossin //!                 slot,
301*4af84c6aSBenno Lossin //!             | -> ::core::result::Result<(), ::core::convert::Infallible> {
302fc6c6baaSBenno Lossin //!                 init(slot).map(|__InitOk| ())
303fc6c6baaSBenno Lossin //!             };
304fc6c6baaSBenno Lossin //!             // Construct the initializer.
305fc6c6baaSBenno Lossin //!             let init = unsafe {
306*4af84c6aSBenno Lossin //!                 ::kernel::init::pin_init_from_closure::<
307*4af84c6aSBenno Lossin //!                     _,
308*4af84c6aSBenno Lossin //!                     ::core::convert::Infallible,
309*4af84c6aSBenno Lossin //!                 >(init)
310fc6c6baaSBenno Lossin //!             };
311fc6c6baaSBenno Lossin //!             init
312fc6c6baaSBenno Lossin //!         }
313fc6c6baaSBenno Lossin //!     }
314fc6c6baaSBenno Lossin //! }
315fc6c6baaSBenno Lossin //! ```
316d0fdc396SBenno Lossin //!
317d0fdc396SBenno Lossin //! ## `#[pin_data]` on `Foo`
318d0fdc396SBenno Lossin //!
319d0fdc396SBenno Lossin //! Since we already took a look at `#[pin_data]` on `Bar`, this section will only explain the
320d0fdc396SBenno Lossin //! differences/new things in the expansion of the `Foo` definition:
321d0fdc396SBenno Lossin //!
322309786c2SBenno Lossin //! ```rust,ignore
323d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)]
324d0fdc396SBenno Lossin //! struct Foo {
325d0fdc396SBenno Lossin //!     a: usize,
326d0fdc396SBenno Lossin //!     #[pin]
327d0fdc396SBenno Lossin //!     b: Bar<u32>,
328d0fdc396SBenno Lossin //! }
329d0fdc396SBenno Lossin //! ```
330d0fdc396SBenno Lossin //!
331d0fdc396SBenno Lossin //! This expands to the following code:
332d0fdc396SBenno Lossin //!
333309786c2SBenno Lossin //! ```rust,ignore
334d0fdc396SBenno Lossin //! struct Foo {
335d0fdc396SBenno Lossin //!     a: usize,
336d0fdc396SBenno Lossin //!     b: Bar<u32>,
337d0fdc396SBenno Lossin //! }
338d0fdc396SBenno Lossin //! const _: () = {
339d0fdc396SBenno Lossin //!     struct __ThePinData {
340d0fdc396SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
341d0fdc396SBenno Lossin //!     }
342d0fdc396SBenno Lossin //!     impl ::core::clone::Clone for __ThePinData {
343d0fdc396SBenno Lossin //!         fn clone(&self) -> Self {
344d0fdc396SBenno Lossin //!             *self
345d0fdc396SBenno Lossin //!         }
346d0fdc396SBenno Lossin //!     }
347d0fdc396SBenno Lossin //!     impl ::core::marker::Copy for __ThePinData {}
348d0fdc396SBenno Lossin //!     #[allow(dead_code)]
349d0fdc396SBenno Lossin //!     impl __ThePinData {
350d0fdc396SBenno Lossin //!         unsafe fn b<E>(
351d0fdc396SBenno Lossin //!             self,
352d0fdc396SBenno Lossin //!             slot: *mut Bar<u32>,
353d0fdc396SBenno Lossin //!             init: impl ::kernel::init::PinInit<Bar<u32>, E>,
354d0fdc396SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
355d0fdc396SBenno Lossin //!             unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
356d0fdc396SBenno Lossin //!         }
357d0fdc396SBenno Lossin //!         unsafe fn a<E>(
358d0fdc396SBenno Lossin //!             self,
359d0fdc396SBenno Lossin //!             slot: *mut usize,
360d0fdc396SBenno Lossin //!             init: impl ::kernel::init::Init<usize, E>,
361d0fdc396SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
362d0fdc396SBenno Lossin //!             unsafe { ::kernel::init::Init::__init(init, slot) }
363d0fdc396SBenno Lossin //!         }
364d0fdc396SBenno Lossin //!     }
365d0fdc396SBenno Lossin //!     unsafe impl ::kernel::init::__internal::HasPinData for Foo {
366d0fdc396SBenno Lossin //!         type PinData = __ThePinData;
367d0fdc396SBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
368d0fdc396SBenno Lossin //!             __ThePinData {
369d0fdc396SBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
370d0fdc396SBenno Lossin //!             }
371d0fdc396SBenno Lossin //!         }
372d0fdc396SBenno Lossin //!     }
373d0fdc396SBenno Lossin //!     unsafe impl ::kernel::init::__internal::PinData for __ThePinData {
374d0fdc396SBenno Lossin //!         type Datee = Foo;
375d0fdc396SBenno Lossin //!     }
376d0fdc396SBenno Lossin //!     #[allow(dead_code)]
377d0fdc396SBenno Lossin //!     struct __Unpin<'__pin> {
378d0fdc396SBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
379d0fdc396SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
380d0fdc396SBenno Lossin //!         b: Bar<u32>,
381d0fdc396SBenno Lossin //!     }
382d0fdc396SBenno Lossin //!     #[doc(hidden)]
383*4af84c6aSBenno Lossin //!     impl<'__pin> ::core::marker::Unpin for Foo
384*4af84c6aSBenno Lossin //!     where
385*4af84c6aSBenno Lossin //!         __Unpin<'__pin>: ::core::marker::Unpin,
386*4af84c6aSBenno Lossin //!     {}
387d0fdc396SBenno Lossin //!     // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to
388d0fdc396SBenno Lossin //!     // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
389309786c2SBenno Lossin //!     // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
390d0fdc396SBenno Lossin //!     impl ::core::ops::Drop for Foo {
391d0fdc396SBenno Lossin //!         fn drop(&mut self) {
392d0fdc396SBenno Lossin //!             // Since we are getting dropped, no one else has a reference to `self` and thus we
393d0fdc396SBenno Lossin //!             // can assume that we never move.
394d0fdc396SBenno Lossin //!             let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
395d0fdc396SBenno Lossin //!             // Create the unsafe token that proves that we are inside of a destructor, this
396d0fdc396SBenno Lossin //!             // type is only allowed to be created in a destructor.
397d0fdc396SBenno Lossin //!             let token = unsafe { ::kernel::init::__internal::OnlyCallFromDrop::new() };
398d0fdc396SBenno Lossin //!             ::kernel::init::PinnedDrop::drop(pinned, token);
399d0fdc396SBenno Lossin //!         }
400d0fdc396SBenno Lossin //!     }
401d0fdc396SBenno Lossin //! };
402d0fdc396SBenno Lossin //! ```
403d0fdc396SBenno Lossin //!
404d0fdc396SBenno Lossin //! ## `#[pinned_drop]` on `impl PinnedDrop for Foo`
405d0fdc396SBenno Lossin //!
406d0fdc396SBenno Lossin //! This macro is used to implement the `PinnedDrop` trait, since that trait is `unsafe` and has an
407d0fdc396SBenno Lossin //! extra parameter that should not be used at all. The macro hides that parameter.
408d0fdc396SBenno Lossin //!
409d0fdc396SBenno Lossin //! Here is the `PinnedDrop` impl for `Foo`:
410d0fdc396SBenno Lossin //!
411309786c2SBenno Lossin //! ```rust,ignore
412d0fdc396SBenno Lossin //! #[pinned_drop]
413d0fdc396SBenno Lossin //! impl PinnedDrop for Foo {
414d0fdc396SBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
415*4af84c6aSBenno Lossin //!         pr_info!("{self:p} is getting dropped.");
416d0fdc396SBenno Lossin //!     }
417d0fdc396SBenno Lossin //! }
418d0fdc396SBenno Lossin //! ```
419d0fdc396SBenno Lossin //!
420d0fdc396SBenno Lossin //! This expands to the following code:
421d0fdc396SBenno Lossin //!
422309786c2SBenno Lossin //! ```rust,ignore
423d0fdc396SBenno Lossin //! // `unsafe`, full path and the token parameter are added, everything else stays the same.
424d0fdc396SBenno Lossin //! unsafe impl ::kernel::init::PinnedDrop for Foo {
425d0fdc396SBenno Lossin //!     fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) {
426*4af84c6aSBenno Lossin //!         pr_info!("{self:p} is getting dropped.");
427d0fdc396SBenno Lossin //!     }
428d0fdc396SBenno Lossin //! }
429d0fdc396SBenno Lossin //! ```
430d0fdc396SBenno Lossin //!
431d0fdc396SBenno Lossin //! ## `pin_init!` on `Foo`
432d0fdc396SBenno Lossin //!
433309786c2SBenno Lossin //! Since we already took a look at `pin_init!` on `Bar`, this section will only show the expansion
434309786c2SBenno Lossin //! of `pin_init!` on `Foo`:
435d0fdc396SBenno Lossin //!
436309786c2SBenno Lossin //! ```rust,ignore
437d0fdc396SBenno Lossin //! let a = 42;
438d0fdc396SBenno Lossin //! let initializer = pin_init!(Foo {
439d0fdc396SBenno Lossin //!     a,
440d0fdc396SBenno Lossin //!     b <- Bar::new(36),
441d0fdc396SBenno Lossin //! });
442d0fdc396SBenno Lossin //! ```
443d0fdc396SBenno Lossin //!
444d0fdc396SBenno Lossin //! This expands to the following code:
445d0fdc396SBenno Lossin //!
446309786c2SBenno Lossin //! ```rust,ignore
447d0fdc396SBenno Lossin //! let a = 42;
448d0fdc396SBenno Lossin //! let initializer = {
449d0fdc396SBenno Lossin //!     struct __InitOk;
450d0fdc396SBenno Lossin //!     let data = unsafe {
451d0fdc396SBenno Lossin //!         use ::kernel::init::__internal::HasPinData;
452d0fdc396SBenno Lossin //!         Foo::__pin_data()
453d0fdc396SBenno Lossin //!     };
454d0fdc396SBenno Lossin //!     let init = ::kernel::init::__internal::PinData::make_closure::<
455d0fdc396SBenno Lossin //!         _,
456d0fdc396SBenno Lossin //!         __InitOk,
457d0fdc396SBenno Lossin //!         ::core::convert::Infallible,
458d0fdc396SBenno Lossin //!     >(data, move |slot| {
459d0fdc396SBenno Lossin //!         {
460d0fdc396SBenno Lossin //!             struct __InitOk;
461*4af84c6aSBenno Lossin //!             {
462309786c2SBenno Lossin //!                 unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
463*4af84c6aSBenno Lossin //!             }
464*4af84c6aSBenno Lossin //!             let a = unsafe {
465309786c2SBenno Lossin //!                 ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
466309786c2SBenno Lossin //!             };
467*4af84c6aSBenno Lossin //!             let init = Bar::new(36);
468309786c2SBenno Lossin //!             unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
469*4af84c6aSBenno Lossin //!             let b = unsafe {
470309786c2SBenno Lossin //!                 ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
471309786c2SBenno Lossin //!             };
472*4af84c6aSBenno Lossin //!             ::core::mem::forget(b);
473*4af84c6aSBenno Lossin //!             ::core::mem::forget(a);
474d0fdc396SBenno Lossin //!             #[allow(unreachable_code, clippy::diverging_sub_expression)]
475*4af84c6aSBenno Lossin //!             let _ = || {
476d0fdc396SBenno Lossin //!                 unsafe {
477d0fdc396SBenno Lossin //!                     ::core::ptr::write(
478d0fdc396SBenno Lossin //!                         slot,
479d0fdc396SBenno Lossin //!                         Foo {
480d0fdc396SBenno Lossin //!                             a: ::core::panic!(),
481d0fdc396SBenno Lossin //!                             b: ::core::panic!(),
482d0fdc396SBenno Lossin //!                         },
483d0fdc396SBenno Lossin //!                     );
484d0fdc396SBenno Lossin //!                 };
485*4af84c6aSBenno Lossin //!             };
486d0fdc396SBenno Lossin //!         }
487d0fdc396SBenno Lossin //!         Ok(__InitOk)
488d0fdc396SBenno Lossin //!     });
489*4af84c6aSBenno Lossin //!     let init = move |
490*4af84c6aSBenno Lossin //!         slot,
491*4af84c6aSBenno Lossin //!     | -> ::core::result::Result<(), ::core::convert::Infallible> {
492d0fdc396SBenno Lossin //!         init(slot).map(|__InitOk| ())
493d0fdc396SBenno Lossin //!     };
494d0fdc396SBenno Lossin //!     let init = unsafe {
495d0fdc396SBenno Lossin //!         ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
496d0fdc396SBenno Lossin //!     };
497d0fdc396SBenno Lossin //!     init
498d0fdc396SBenno Lossin //! };
499d0fdc396SBenno Lossin //! ```
500d0fdc396SBenno Lossin 
501d0fdc396SBenno Lossin /// Creates a `unsafe impl<...> PinnedDrop for $type` block.
502d0fdc396SBenno Lossin ///
503d0fdc396SBenno Lossin /// See [`PinnedDrop`] for more information.
504d0fdc396SBenno Lossin #[doc(hidden)]
505d0fdc396SBenno Lossin #[macro_export]
506d0fdc396SBenno Lossin macro_rules! __pinned_drop {
507d0fdc396SBenno Lossin     (
508d0fdc396SBenno Lossin         @impl_sig($($impl_sig:tt)*),
509d0fdc396SBenno Lossin         @impl_body(
510d0fdc396SBenno Lossin             $(#[$($attr:tt)*])*
511d0fdc396SBenno Lossin             fn drop($($sig:tt)*) {
512d0fdc396SBenno Lossin                 $($inner:tt)*
513d0fdc396SBenno Lossin             }
514d0fdc396SBenno Lossin         ),
515d0fdc396SBenno Lossin     ) => {
516d0fdc396SBenno Lossin         unsafe $($impl_sig)* {
517d0fdc396SBenno Lossin             // Inherit all attributes and the type/ident tokens for the signature.
518d0fdc396SBenno Lossin             $(#[$($attr)*])*
519d0fdc396SBenno Lossin             fn drop($($sig)*, _: $crate::init::__internal::OnlyCallFromDrop) {
520d0fdc396SBenno Lossin                 $($inner)*
521d0fdc396SBenno Lossin             }
522d0fdc396SBenno Lossin         }
523d0fdc396SBenno Lossin     }
524d0fdc396SBenno Lossin }
525fc6c6baaSBenno Lossin 
526fc6c6baaSBenno Lossin /// This macro first parses the struct definition such that it separates pinned and not pinned
527fc6c6baaSBenno Lossin /// fields. Afterwards it declares the struct and implement the `PinData` trait safely.
528fc6c6baaSBenno Lossin #[doc(hidden)]
529fc6c6baaSBenno Lossin #[macro_export]
530fc6c6baaSBenno Lossin macro_rules! __pin_data {
531fc6c6baaSBenno Lossin     // Proc-macro entry point, this is supplied by the proc-macro pre-parsing.
532fc6c6baaSBenno Lossin     (parse_input:
533fc6c6baaSBenno Lossin         @args($($pinned_drop:ident)?),
534fc6c6baaSBenno Lossin         @sig(
535fc6c6baaSBenno Lossin             $(#[$($struct_attr:tt)*])*
536fc6c6baaSBenno Lossin             $vis:vis struct $name:ident
537fc6c6baaSBenno Lossin             $(where $($whr:tt)*)?
538fc6c6baaSBenno Lossin         ),
539fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
540fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
541fc6c6baaSBenno Lossin         @body({ $($fields:tt)* }),
542fc6c6baaSBenno Lossin     ) => {
543fc6c6baaSBenno Lossin         // We now use token munching to iterate through all of the fields. While doing this we
544fc6c6baaSBenno Lossin         // identify fields marked with `#[pin]`, these fields are the 'pinned fields'. The user
545fc6c6baaSBenno Lossin         // wants these to be structurally pinned. The rest of the fields are the
546fc6c6baaSBenno Lossin         // 'not pinned fields'. Additionally we collect all fields, since we need them in the right
547fc6c6baaSBenno Lossin         // order to declare the struct.
548fc6c6baaSBenno Lossin         //
549fc6c6baaSBenno Lossin         // In this call we also put some explaining comments for the parameters.
550fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
551fc6c6baaSBenno Lossin             // Attributes on the struct itself, these will just be propagated to be put onto the
552fc6c6baaSBenno Lossin             // struct definition.
553fc6c6baaSBenno Lossin             @struct_attrs($(#[$($struct_attr)*])*),
554fc6c6baaSBenno Lossin             // The visibility of the struct.
555fc6c6baaSBenno Lossin             @vis($vis),
556fc6c6baaSBenno Lossin             // The name of the struct.
557fc6c6baaSBenno Lossin             @name($name),
558fc6c6baaSBenno Lossin             // The 'impl generics', the generics that will need to be specified on the struct inside
559fc6c6baaSBenno Lossin             // of an `impl<$ty_generics>` block.
560fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
561fc6c6baaSBenno Lossin             // The 'ty generics', the generics that will need to be specified on the impl blocks.
562fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
563fc6c6baaSBenno Lossin             // The where clause of any impl block and the declaration.
564fc6c6baaSBenno Lossin             @where($($($whr)*)?),
565fc6c6baaSBenno Lossin             // The remaining fields tokens that need to be processed.
566fc6c6baaSBenno Lossin             // We add a `,` at the end to ensure correct parsing.
567fc6c6baaSBenno Lossin             @fields_munch($($fields)* ,),
568fc6c6baaSBenno Lossin             // The pinned fields.
569fc6c6baaSBenno Lossin             @pinned(),
570fc6c6baaSBenno Lossin             // The not pinned fields.
571fc6c6baaSBenno Lossin             @not_pinned(),
572fc6c6baaSBenno Lossin             // All fields.
573fc6c6baaSBenno Lossin             @fields(),
574fc6c6baaSBenno Lossin             // The accumulator containing all attributes already parsed.
575fc6c6baaSBenno Lossin             @accum(),
576fc6c6baaSBenno Lossin             // Contains `yes` or `` to indicate if `#[pin]` was found on the current field.
577fc6c6baaSBenno Lossin             @is_pinned(),
578fc6c6baaSBenno Lossin             // The proc-macro argument, this should be `PinnedDrop` or ``.
579fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
580fc6c6baaSBenno Lossin         );
581fc6c6baaSBenno Lossin     };
582fc6c6baaSBenno Lossin     (find_pinned_fields:
583fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
584fc6c6baaSBenno Lossin         @vis($vis:vis),
585fc6c6baaSBenno Lossin         @name($name:ident),
586fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
587fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
588fc6c6baaSBenno Lossin         @where($($whr:tt)*),
589fc6c6baaSBenno Lossin         // We found a PhantomPinned field, this should generally be pinned!
590fc6c6baaSBenno Lossin         @fields_munch($field:ident : $($($(::)?core::)?marker::)?PhantomPinned, $($rest:tt)*),
591fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
592fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
593fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
594fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
595fc6c6baaSBenno Lossin         // This field is not pinned.
596fc6c6baaSBenno Lossin         @is_pinned(),
597fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
598fc6c6baaSBenno Lossin     ) => {
599fc6c6baaSBenno Lossin         ::core::compile_error!(concat!(
600fc6c6baaSBenno Lossin             "The field `",
601fc6c6baaSBenno Lossin             stringify!($field),
602fc6c6baaSBenno Lossin             "` of type `PhantomPinned` only has an effect, if it has the `#[pin]` attribute.",
603fc6c6baaSBenno Lossin         ));
604fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
605fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
606fc6c6baaSBenno Lossin             @vis($vis),
607fc6c6baaSBenno Lossin             @name($name),
608fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
609fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
610fc6c6baaSBenno Lossin             @where($($whr)*),
611fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
612fc6c6baaSBenno Lossin             @pinned($($pinned)* $($accum)* $field: ::core::marker::PhantomPinned,),
613fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
614fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: ::core::marker::PhantomPinned,),
615fc6c6baaSBenno Lossin             @accum(),
616fc6c6baaSBenno Lossin             @is_pinned(),
617fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
618fc6c6baaSBenno Lossin         );
619fc6c6baaSBenno Lossin     };
620fc6c6baaSBenno Lossin     (find_pinned_fields:
621fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
622fc6c6baaSBenno Lossin         @vis($vis:vis),
623fc6c6baaSBenno Lossin         @name($name:ident),
624fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
625fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
626fc6c6baaSBenno Lossin         @where($($whr:tt)*),
627fc6c6baaSBenno Lossin         // We reached the field declaration.
628fc6c6baaSBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
629fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
630fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
631fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
632fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
633fc6c6baaSBenno Lossin         // This field is pinned.
634fc6c6baaSBenno Lossin         @is_pinned(yes),
635fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
636fc6c6baaSBenno Lossin     ) => {
637fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
638fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
639fc6c6baaSBenno Lossin             @vis($vis),
640fc6c6baaSBenno Lossin             @name($name),
641fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
642fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
643fc6c6baaSBenno Lossin             @where($($whr)*),
644fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
645fc6c6baaSBenno Lossin             @pinned($($pinned)* $($accum)* $field: $type,),
646fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
647fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
648fc6c6baaSBenno Lossin             @accum(),
649fc6c6baaSBenno Lossin             @is_pinned(),
650fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
651fc6c6baaSBenno Lossin         );
652fc6c6baaSBenno Lossin     };
653fc6c6baaSBenno Lossin     (find_pinned_fields:
654fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
655fc6c6baaSBenno Lossin         @vis($vis:vis),
656fc6c6baaSBenno Lossin         @name($name:ident),
657fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
658fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
659fc6c6baaSBenno Lossin         @where($($whr:tt)*),
660fc6c6baaSBenno Lossin         // We reached the field declaration.
661fc6c6baaSBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
662fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
663fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
664fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
665fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
666fc6c6baaSBenno Lossin         // This field is not pinned.
667fc6c6baaSBenno Lossin         @is_pinned(),
668fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
669fc6c6baaSBenno Lossin     ) => {
670fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
671fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
672fc6c6baaSBenno Lossin             @vis($vis),
673fc6c6baaSBenno Lossin             @name($name),
674fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
675fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
676fc6c6baaSBenno Lossin             @where($($whr)*),
677fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
678fc6c6baaSBenno Lossin             @pinned($($pinned)*),
679fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)* $($accum)* $field: $type,),
680fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
681fc6c6baaSBenno Lossin             @accum(),
682fc6c6baaSBenno Lossin             @is_pinned(),
683fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
684fc6c6baaSBenno Lossin         );
685fc6c6baaSBenno Lossin     };
686fc6c6baaSBenno Lossin     (find_pinned_fields:
687fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
688fc6c6baaSBenno Lossin         @vis($vis:vis),
689fc6c6baaSBenno Lossin         @name($name:ident),
690fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
691fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
692fc6c6baaSBenno Lossin         @where($($whr:tt)*),
693fc6c6baaSBenno Lossin         // We found the `#[pin]` attr.
694fc6c6baaSBenno Lossin         @fields_munch(#[pin] $($rest:tt)*),
695fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
696fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
697fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
698fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
699fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
700fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
701fc6c6baaSBenno Lossin     ) => {
702fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
703fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
704fc6c6baaSBenno Lossin             @vis($vis),
705fc6c6baaSBenno Lossin             @name($name),
706fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
707fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
708fc6c6baaSBenno Lossin             @where($($whr)*),
709fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
710fc6c6baaSBenno Lossin             // We do not include `#[pin]` in the list of attributes, since it is not actually an
711fc6c6baaSBenno Lossin             // attribute that is defined somewhere.
712fc6c6baaSBenno Lossin             @pinned($($pinned)*),
713fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
714fc6c6baaSBenno Lossin             @fields($($fields)*),
715fc6c6baaSBenno Lossin             @accum($($accum)*),
716fc6c6baaSBenno Lossin             // Set this to `yes`.
717fc6c6baaSBenno Lossin             @is_pinned(yes),
718fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
719fc6c6baaSBenno Lossin         );
720fc6c6baaSBenno Lossin     };
721fc6c6baaSBenno Lossin     (find_pinned_fields:
722fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
723fc6c6baaSBenno Lossin         @vis($vis:vis),
724fc6c6baaSBenno Lossin         @name($name:ident),
725fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
726fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
727fc6c6baaSBenno Lossin         @where($($whr:tt)*),
728fc6c6baaSBenno Lossin         // We reached the field declaration with visibility, for simplicity we only munch the
729fc6c6baaSBenno Lossin         // visibility and put it into `$accum`.
730fc6c6baaSBenno Lossin         @fields_munch($fvis:vis $field:ident $($rest:tt)*),
731fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
732fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
733fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
734fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
735fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
736fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
737fc6c6baaSBenno Lossin     ) => {
738fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
739fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
740fc6c6baaSBenno Lossin             @vis($vis),
741fc6c6baaSBenno Lossin             @name($name),
742fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
743fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
744fc6c6baaSBenno Lossin             @where($($whr)*),
745fc6c6baaSBenno Lossin             @fields_munch($field $($rest)*),
746fc6c6baaSBenno Lossin             @pinned($($pinned)*),
747fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
748fc6c6baaSBenno Lossin             @fields($($fields)*),
749fc6c6baaSBenno Lossin             @accum($($accum)* $fvis),
750fc6c6baaSBenno Lossin             @is_pinned($($is_pinned)?),
751fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
752fc6c6baaSBenno Lossin         );
753fc6c6baaSBenno Lossin     };
754fc6c6baaSBenno Lossin     (find_pinned_fields:
755fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
756fc6c6baaSBenno Lossin         @vis($vis:vis),
757fc6c6baaSBenno Lossin         @name($name:ident),
758fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
759fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
760fc6c6baaSBenno Lossin         @where($($whr:tt)*),
761fc6c6baaSBenno Lossin         // Some other attribute, just put it into `$accum`.
762fc6c6baaSBenno Lossin         @fields_munch(#[$($attr:tt)*] $($rest:tt)*),
763fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
764fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
765fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
766fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
767fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
768fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
769fc6c6baaSBenno Lossin     ) => {
770fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
771fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
772fc6c6baaSBenno Lossin             @vis($vis),
773fc6c6baaSBenno Lossin             @name($name),
774fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
775fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
776fc6c6baaSBenno Lossin             @where($($whr)*),
777fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
778fc6c6baaSBenno Lossin             @pinned($($pinned)*),
779fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
780fc6c6baaSBenno Lossin             @fields($($fields)*),
781fc6c6baaSBenno Lossin             @accum($($accum)* #[$($attr)*]),
782fc6c6baaSBenno Lossin             @is_pinned($($is_pinned)?),
783fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
784fc6c6baaSBenno Lossin         );
785fc6c6baaSBenno Lossin     };
786fc6c6baaSBenno Lossin     (find_pinned_fields:
787fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
788fc6c6baaSBenno Lossin         @vis($vis:vis),
789fc6c6baaSBenno Lossin         @name($name:ident),
790fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
791fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
792fc6c6baaSBenno Lossin         @where($($whr:tt)*),
793fc6c6baaSBenno Lossin         // We reached the end of the fields, plus an optional additional comma, since we added one
794fc6c6baaSBenno Lossin         // before and the user is also allowed to put a trailing comma.
795fc6c6baaSBenno Lossin         @fields_munch($(,)?),
796fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
797fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
798fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
799fc6c6baaSBenno Lossin         @accum(),
800fc6c6baaSBenno Lossin         @is_pinned(),
801fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
802fc6c6baaSBenno Lossin     ) => {
803fc6c6baaSBenno Lossin         // Declare the struct with all fields in the correct order.
804fc6c6baaSBenno Lossin         $($struct_attrs)*
805fc6c6baaSBenno Lossin         $vis struct $name <$($impl_generics)*>
806fc6c6baaSBenno Lossin         where $($whr)*
807fc6c6baaSBenno Lossin         {
808fc6c6baaSBenno Lossin             $($fields)*
809fc6c6baaSBenno Lossin         }
810fc6c6baaSBenno Lossin 
811fc6c6baaSBenno Lossin         // We put the rest into this const item, because it then will not be accessible to anything
812fc6c6baaSBenno Lossin         // outside.
813fc6c6baaSBenno Lossin         const _: () = {
814fc6c6baaSBenno Lossin             // We declare this struct which will host all of the projection function for our type.
815fc6c6baaSBenno Lossin             // it will be invariant over all generic parameters which are inherited from the
816fc6c6baaSBenno Lossin             // struct.
817fc6c6baaSBenno Lossin             $vis struct __ThePinData<$($impl_generics)*>
818fc6c6baaSBenno Lossin             where $($whr)*
819fc6c6baaSBenno Lossin             {
820fc6c6baaSBenno Lossin                 __phantom: ::core::marker::PhantomData<
821fc6c6baaSBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
822fc6c6baaSBenno Lossin                 >,
823fc6c6baaSBenno Lossin             }
824fc6c6baaSBenno Lossin 
825fc6c6baaSBenno Lossin             impl<$($impl_generics)*> ::core::clone::Clone for __ThePinData<$($ty_generics)*>
826fc6c6baaSBenno Lossin             where $($whr)*
827fc6c6baaSBenno Lossin             {
828fc6c6baaSBenno Lossin                 fn clone(&self) -> Self { *self }
829fc6c6baaSBenno Lossin             }
830fc6c6baaSBenno Lossin 
831fc6c6baaSBenno Lossin             impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*>
832fc6c6baaSBenno Lossin             where $($whr)*
833fc6c6baaSBenno Lossin             {}
834fc6c6baaSBenno Lossin 
835fc6c6baaSBenno Lossin             // Make all projection functions.
836fc6c6baaSBenno Lossin             $crate::__pin_data!(make_pin_data:
837fc6c6baaSBenno Lossin                 @pin_data(__ThePinData),
838fc6c6baaSBenno Lossin                 @impl_generics($($impl_generics)*),
839fc6c6baaSBenno Lossin                 @ty_generics($($ty_generics)*),
840fc6c6baaSBenno Lossin                 @where($($whr)*),
841fc6c6baaSBenno Lossin                 @pinned($($pinned)*),
842fc6c6baaSBenno Lossin                 @not_pinned($($not_pinned)*),
843fc6c6baaSBenno Lossin             );
844fc6c6baaSBenno Lossin 
845fc6c6baaSBenno Lossin             // SAFETY: We have added the correct projection functions above to `__ThePinData` and
846fc6c6baaSBenno Lossin             // we also use the least restrictive generics possible.
847fc6c6baaSBenno Lossin             unsafe impl<$($impl_generics)*>
848fc6c6baaSBenno Lossin                 $crate::init::__internal::HasPinData for $name<$($ty_generics)*>
849fc6c6baaSBenno Lossin             where $($whr)*
850fc6c6baaSBenno Lossin             {
851fc6c6baaSBenno Lossin                 type PinData = __ThePinData<$($ty_generics)*>;
852fc6c6baaSBenno Lossin 
853fc6c6baaSBenno Lossin                 unsafe fn __pin_data() -> Self::PinData {
854fc6c6baaSBenno Lossin                     __ThePinData { __phantom: ::core::marker::PhantomData }
855fc6c6baaSBenno Lossin                 }
856fc6c6baaSBenno Lossin             }
857fc6c6baaSBenno Lossin 
858fc6c6baaSBenno Lossin             unsafe impl<$($impl_generics)*>
859fc6c6baaSBenno Lossin                 $crate::init::__internal::PinData for __ThePinData<$($ty_generics)*>
860fc6c6baaSBenno Lossin             where $($whr)*
861fc6c6baaSBenno Lossin             {
862fc6c6baaSBenno Lossin                 type Datee = $name<$($ty_generics)*>;
863fc6c6baaSBenno Lossin             }
864fc6c6baaSBenno Lossin 
865fc6c6baaSBenno Lossin             // This struct will be used for the unpin analysis. Since only structurally pinned
866fc6c6baaSBenno Lossin             // fields are relevant whether the struct should implement `Unpin`.
867fc6c6baaSBenno Lossin             #[allow(dead_code)]
868fc6c6baaSBenno Lossin             struct __Unpin <'__pin, $($impl_generics)*>
869fc6c6baaSBenno Lossin             where $($whr)*
870fc6c6baaSBenno Lossin             {
871fc6c6baaSBenno Lossin                 __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
872fc6c6baaSBenno Lossin                 __phantom: ::core::marker::PhantomData<
873fc6c6baaSBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
874fc6c6baaSBenno Lossin                 >,
875fc6c6baaSBenno Lossin                 // Only the pinned fields.
876fc6c6baaSBenno Lossin                 $($pinned)*
877fc6c6baaSBenno Lossin             }
878fc6c6baaSBenno Lossin 
879fc6c6baaSBenno Lossin             #[doc(hidden)]
880fc6c6baaSBenno Lossin             impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*>
881fc6c6baaSBenno Lossin             where
882fc6c6baaSBenno Lossin                 __Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin,
883fc6c6baaSBenno Lossin                 $($whr)*
884fc6c6baaSBenno Lossin             {}
885fc6c6baaSBenno Lossin 
886fc6c6baaSBenno Lossin             // We need to disallow normal `Drop` implementation, the exact behavior depends on
887fc6c6baaSBenno Lossin             // whether `PinnedDrop` was specified as the parameter.
888fc6c6baaSBenno Lossin             $crate::__pin_data!(drop_prevention:
889fc6c6baaSBenno Lossin                 @name($name),
890fc6c6baaSBenno Lossin                 @impl_generics($($impl_generics)*),
891fc6c6baaSBenno Lossin                 @ty_generics($($ty_generics)*),
892fc6c6baaSBenno Lossin                 @where($($whr)*),
893fc6c6baaSBenno Lossin                 @pinned_drop($($pinned_drop)?),
894fc6c6baaSBenno Lossin             );
895fc6c6baaSBenno Lossin         };
896fc6c6baaSBenno Lossin     };
897fc6c6baaSBenno Lossin     // When no `PinnedDrop` was specified, then we have to prevent implementing drop.
898fc6c6baaSBenno Lossin     (drop_prevention:
899fc6c6baaSBenno Lossin         @name($name:ident),
900fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
901fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
902fc6c6baaSBenno Lossin         @where($($whr:tt)*),
903fc6c6baaSBenno Lossin         @pinned_drop(),
904fc6c6baaSBenno Lossin     ) => {
905fc6c6baaSBenno Lossin         // We prevent this by creating a trait that will be implemented for all types implementing
906fc6c6baaSBenno Lossin         // `Drop`. Additionally we will implement this trait for the struct leading to a conflict,
907fc6c6baaSBenno Lossin         // if it also implements `Drop`
908fc6c6baaSBenno Lossin         trait MustNotImplDrop {}
909fc6c6baaSBenno Lossin         #[allow(drop_bounds)]
910fc6c6baaSBenno Lossin         impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
911fc6c6baaSBenno Lossin         impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*>
912fc6c6baaSBenno Lossin         where $($whr)* {}
913d0fdc396SBenno Lossin         // We also take care to prevent users from writing a useless `PinnedDrop` implementation.
914d0fdc396SBenno Lossin         // They might implement `PinnedDrop` correctly for the struct, but forget to give
915d0fdc396SBenno Lossin         // `PinnedDrop` as the parameter to `#[pin_data]`.
916d0fdc396SBenno Lossin         #[allow(non_camel_case_types)]
917d0fdc396SBenno Lossin         trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
918d0fdc396SBenno Lossin         impl<T: $crate::init::PinnedDrop>
919d0fdc396SBenno Lossin             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
920d0fdc396SBenno Lossin         impl<$($impl_generics)*>
921d0fdc396SBenno Lossin             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for $name<$($ty_generics)*>
922d0fdc396SBenno Lossin         where $($whr)* {}
923d0fdc396SBenno Lossin     };
924d0fdc396SBenno Lossin     // When `PinnedDrop` was specified we just implement `Drop` and delegate.
925d0fdc396SBenno Lossin     (drop_prevention:
926d0fdc396SBenno Lossin         @name($name:ident),
927d0fdc396SBenno Lossin         @impl_generics($($impl_generics:tt)*),
928d0fdc396SBenno Lossin         @ty_generics($($ty_generics:tt)*),
929d0fdc396SBenno Lossin         @where($($whr:tt)*),
930d0fdc396SBenno Lossin         @pinned_drop(PinnedDrop),
931d0fdc396SBenno Lossin     ) => {
932d0fdc396SBenno Lossin         impl<$($impl_generics)*> ::core::ops::Drop for $name<$($ty_generics)*>
933d0fdc396SBenno Lossin         where $($whr)*
934d0fdc396SBenno Lossin         {
935d0fdc396SBenno Lossin             fn drop(&mut self) {
936d0fdc396SBenno Lossin                 // SAFETY: Since this is a destructor, `self` will not move after this function
937d0fdc396SBenno Lossin                 // terminates, since it is inaccessible.
938d0fdc396SBenno Lossin                 let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
939d0fdc396SBenno Lossin                 // SAFETY: Since this is a drop function, we can create this token to call the
940d0fdc396SBenno Lossin                 // pinned destructor of this type.
941d0fdc396SBenno Lossin                 let token = unsafe { $crate::init::__internal::OnlyCallFromDrop::new() };
942d0fdc396SBenno Lossin                 $crate::init::PinnedDrop::drop(pinned, token);
943d0fdc396SBenno Lossin             }
944d0fdc396SBenno Lossin         }
945fc6c6baaSBenno Lossin     };
946fc6c6baaSBenno Lossin     // If some other parameter was specified, we emit a readable error.
947fc6c6baaSBenno Lossin     (drop_prevention:
948fc6c6baaSBenno Lossin         @name($name:ident),
949fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
950fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
951fc6c6baaSBenno Lossin         @where($($whr:tt)*),
952fc6c6baaSBenno Lossin         @pinned_drop($($rest:tt)*),
953fc6c6baaSBenno Lossin     ) => {
954fc6c6baaSBenno Lossin         compile_error!(
955fc6c6baaSBenno Lossin             "Wrong parameters to `#[pin_data]`, expected nothing or `PinnedDrop`, got '{}'.",
956fc6c6baaSBenno Lossin             stringify!($($rest)*),
957fc6c6baaSBenno Lossin         );
958fc6c6baaSBenno Lossin     };
959fc6c6baaSBenno Lossin     (make_pin_data:
960fc6c6baaSBenno Lossin         @pin_data($pin_data:ident),
961fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
962fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
963fc6c6baaSBenno Lossin         @where($($whr:tt)*),
964fc6c6baaSBenno Lossin         @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
965fc6c6baaSBenno Lossin         @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
966fc6c6baaSBenno Lossin     ) => {
967fc6c6baaSBenno Lossin         // For every field, we create a projection function according to its projection type. If a
968fc6c6baaSBenno Lossin         // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
969fc6c6baaSBenno Lossin         // structurally pinned, then it can be initialized via `Init`.
970fc6c6baaSBenno Lossin         //
971fc6c6baaSBenno Lossin         // The functions are `unsafe` to prevent accidentally calling them.
972fc6c6baaSBenno Lossin         #[allow(dead_code)]
973fc6c6baaSBenno Lossin         impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
974fc6c6baaSBenno Lossin         where $($whr)*
975fc6c6baaSBenno Lossin         {
976fc6c6baaSBenno Lossin             $(
977f8badd15SBenno Lossin                 $(#[$($p_attr)*])*
978fc6c6baaSBenno Lossin                 $pvis unsafe fn $p_field<E>(
979fc6c6baaSBenno Lossin                     self,
980fc6c6baaSBenno Lossin                     slot: *mut $p_type,
981fc6c6baaSBenno Lossin                     init: impl $crate::init::PinInit<$p_type, E>,
982fc6c6baaSBenno Lossin                 ) -> ::core::result::Result<(), E> {
983fc6c6baaSBenno Lossin                     unsafe { $crate::init::PinInit::__pinned_init(init, slot) }
984fc6c6baaSBenno Lossin                 }
985fc6c6baaSBenno Lossin             )*
986fc6c6baaSBenno Lossin             $(
987f8badd15SBenno Lossin                 $(#[$($attr)*])*
988fc6c6baaSBenno Lossin                 $fvis unsafe fn $field<E>(
989fc6c6baaSBenno Lossin                     self,
990fc6c6baaSBenno Lossin                     slot: *mut $type,
991fc6c6baaSBenno Lossin                     init: impl $crate::init::Init<$type, E>,
992fc6c6baaSBenno Lossin                 ) -> ::core::result::Result<(), E> {
993fc6c6baaSBenno Lossin                     unsafe { $crate::init::Init::__init(init, slot) }
994fc6c6baaSBenno Lossin                 }
995fc6c6baaSBenno Lossin             )*
996fc6c6baaSBenno Lossin         }
997fc6c6baaSBenno Lossin     };
998fc6c6baaSBenno Lossin }
999b3068ac3SBenno Lossin 
1000b3068ac3SBenno Lossin /// The internal init macro. Do not call manually!
1001b3068ac3SBenno Lossin ///
1002b3068ac3SBenno Lossin /// This is called by the `{try_}{pin_}init!` macros with various inputs.
1003b3068ac3SBenno Lossin ///
1004b3068ac3SBenno Lossin /// This macro has multiple internal call configurations, these are always the very first ident:
1005b3068ac3SBenno Lossin /// - nothing: this is the base case and called by the `{try_}{pin_}init!` macros.
100635e7fca2SBenno Lossin /// - `with_update_parsed`: when the `..Zeroable::zeroed()` syntax has been handled.
1007b3068ac3SBenno Lossin /// - `init_slot`: recursively creates the code that initializes all fields in `slot`.
1008b3068ac3SBenno Lossin /// - `make_initializer`: recursively create the struct initializer that guarantees that every
1009b3068ac3SBenno Lossin ///   field has been initialized exactly once.
1010b3068ac3SBenno Lossin #[doc(hidden)]
1011b3068ac3SBenno Lossin #[macro_export]
1012b3068ac3SBenno Lossin macro_rules! __init_internal {
1013b3068ac3SBenno Lossin     (
1014b3068ac3SBenno Lossin         @this($($this:ident)?),
1015674b1c7aSBenno Lossin         @typ($t:path),
1016b3068ac3SBenno Lossin         @fields($($fields:tt)*),
1017b3068ac3SBenno Lossin         @error($err:ty),
1018b3068ac3SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
1019b3068ac3SBenno Lossin         // case.
1020b3068ac3SBenno Lossin         @data($data:ident, $($use_data:ident)?),
1021b3068ac3SBenno Lossin         // `HasPinData` or `HasInitData`.
1022b3068ac3SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
1023b3068ac3SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
1024b3068ac3SBenno Lossin         @construct_closure($construct_closure:ident),
102535e7fca2SBenno Lossin         @munch_fields(),
102635e7fca2SBenno Lossin     ) => {
102735e7fca2SBenno Lossin         $crate::__init_internal!(with_update_parsed:
102835e7fca2SBenno Lossin             @this($($this)?),
1029674b1c7aSBenno Lossin             @typ($t),
103035e7fca2SBenno Lossin             @fields($($fields)*),
103135e7fca2SBenno Lossin             @error($err),
103235e7fca2SBenno Lossin             @data($data, $($use_data)?),
103335e7fca2SBenno Lossin             @has_data($has_data, $get_data),
103435e7fca2SBenno Lossin             @construct_closure($construct_closure),
103535e7fca2SBenno Lossin             @zeroed(), // Nothing means default behavior.
103635e7fca2SBenno Lossin         )
103735e7fca2SBenno Lossin     };
103835e7fca2SBenno Lossin     (
103935e7fca2SBenno Lossin         @this($($this:ident)?),
1040674b1c7aSBenno Lossin         @typ($t:path),
104135e7fca2SBenno Lossin         @fields($($fields:tt)*),
104235e7fca2SBenno Lossin         @error($err:ty),
104335e7fca2SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
104435e7fca2SBenno Lossin         // case.
104535e7fca2SBenno Lossin         @data($data:ident, $($use_data:ident)?),
104635e7fca2SBenno Lossin         // `HasPinData` or `HasInitData`.
104735e7fca2SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
104835e7fca2SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
104935e7fca2SBenno Lossin         @construct_closure($construct_closure:ident),
105035e7fca2SBenno Lossin         @munch_fields(..Zeroable::zeroed()),
105135e7fca2SBenno Lossin     ) => {
105235e7fca2SBenno Lossin         $crate::__init_internal!(with_update_parsed:
105335e7fca2SBenno Lossin             @this($($this)?),
1054674b1c7aSBenno Lossin             @typ($t),
105535e7fca2SBenno Lossin             @fields($($fields)*),
105635e7fca2SBenno Lossin             @error($err),
105735e7fca2SBenno Lossin             @data($data, $($use_data)?),
105835e7fca2SBenno Lossin             @has_data($has_data, $get_data),
105935e7fca2SBenno Lossin             @construct_closure($construct_closure),
106035e7fca2SBenno Lossin             @zeroed(()), // `()` means zero all fields not mentioned.
106135e7fca2SBenno Lossin         )
106235e7fca2SBenno Lossin     };
106335e7fca2SBenno Lossin     (
106435e7fca2SBenno Lossin         @this($($this:ident)?),
1065674b1c7aSBenno Lossin         @typ($t:path),
106635e7fca2SBenno Lossin         @fields($($fields:tt)*),
106735e7fca2SBenno Lossin         @error($err:ty),
106835e7fca2SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
106935e7fca2SBenno Lossin         // case.
107035e7fca2SBenno Lossin         @data($data:ident, $($use_data:ident)?),
107135e7fca2SBenno Lossin         // `HasPinData` or `HasInitData`.
107235e7fca2SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
107335e7fca2SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
107435e7fca2SBenno Lossin         @construct_closure($construct_closure:ident),
107535e7fca2SBenno Lossin         @munch_fields($ignore:tt $($rest:tt)*),
107635e7fca2SBenno Lossin     ) => {
107735e7fca2SBenno Lossin         $crate::__init_internal!(
107835e7fca2SBenno Lossin             @this($($this)?),
1079674b1c7aSBenno Lossin             @typ($t),
108035e7fca2SBenno Lossin             @fields($($fields)*),
108135e7fca2SBenno Lossin             @error($err),
108235e7fca2SBenno Lossin             @data($data, $($use_data)?),
108335e7fca2SBenno Lossin             @has_data($has_data, $get_data),
108435e7fca2SBenno Lossin             @construct_closure($construct_closure),
108535e7fca2SBenno Lossin             @munch_fields($($rest)*),
108635e7fca2SBenno Lossin         )
108735e7fca2SBenno Lossin     };
108835e7fca2SBenno Lossin     (with_update_parsed:
108935e7fca2SBenno Lossin         @this($($this:ident)?),
1090674b1c7aSBenno Lossin         @typ($t:path),
109135e7fca2SBenno Lossin         @fields($($fields:tt)*),
109235e7fca2SBenno Lossin         @error($err:ty),
109335e7fca2SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
109435e7fca2SBenno Lossin         // case.
109535e7fca2SBenno Lossin         @data($data:ident, $($use_data:ident)?),
109635e7fca2SBenno Lossin         // `HasPinData` or `HasInitData`.
109735e7fca2SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
109835e7fca2SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
109935e7fca2SBenno Lossin         @construct_closure($construct_closure:ident),
110035e7fca2SBenno Lossin         @zeroed($($init_zeroed:expr)?),
1101b3068ac3SBenno Lossin     ) => {{
1102b3068ac3SBenno Lossin         // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
1103b3068ac3SBenno Lossin         // type and shadow it later when we insert the arbitrary user code. That way there will be
1104b3068ac3SBenno Lossin         // no possibility of returning without `unsafe`.
1105b3068ac3SBenno Lossin         struct __InitOk;
1106b3068ac3SBenno Lossin         // Get the data about fields from the supplied type.
1107b3068ac3SBenno Lossin         let data = unsafe {
1108b3068ac3SBenno Lossin             use $crate::init::__internal::$has_data;
1109674b1c7aSBenno Lossin             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1110674b1c7aSBenno Lossin             // information that is associated to already parsed fragments, so a path fragment
1111674b1c7aSBenno Lossin             // cannot be used in this position. Doing the retokenization results in valid rust
1112674b1c7aSBenno Lossin             // code.
1113674b1c7aSBenno Lossin             ::kernel::macros::paste!($t::$get_data())
1114b3068ac3SBenno Lossin         };
1115b3068ac3SBenno Lossin         // Ensure that `data` really is of type `$data` and help with type inference:
1116b3068ac3SBenno Lossin         let init = $crate::init::__internal::$data::make_closure::<_, __InitOk, $err>(
1117b3068ac3SBenno Lossin             data,
1118b3068ac3SBenno Lossin             move |slot| {
1119b3068ac3SBenno Lossin                 {
1120b3068ac3SBenno Lossin                     // Shadow the structure so it cannot be used to return early.
1121b3068ac3SBenno Lossin                     struct __InitOk;
112235e7fca2SBenno Lossin                     // If `$init_zeroed` is present we should zero the slot now and not emit an
112335e7fca2SBenno Lossin                     // error when fields are missing (since they will be zeroed). We also have to
112435e7fca2SBenno Lossin                     // check that the type actually implements `Zeroable`.
112535e7fca2SBenno Lossin                     $({
112635e7fca2SBenno Lossin                         fn assert_zeroable<T: $crate::init::Zeroable>(_: *mut T) {}
112735e7fca2SBenno Lossin                         // Ensure that the struct is indeed `Zeroable`.
112835e7fca2SBenno Lossin                         assert_zeroable(slot);
112935e7fca2SBenno Lossin                         // SAFETY: The type implements `Zeroable` by the check above.
113035e7fca2SBenno Lossin                         unsafe { ::core::ptr::write_bytes(slot, 0, 1) };
113135e7fca2SBenno Lossin                         $init_zeroed // This will be `()` if set.
113235e7fca2SBenno Lossin                     })?
1133b3068ac3SBenno Lossin                     // Create the `this` so it can be referenced by the user inside of the
1134b3068ac3SBenno Lossin                     // expressions creating the individual fields.
1135b3068ac3SBenno Lossin                     $(let $this = unsafe { ::core::ptr::NonNull::new_unchecked(slot) };)?
1136b3068ac3SBenno Lossin                     // Initialize every field.
1137b3068ac3SBenno Lossin                     $crate::__init_internal!(init_slot($($use_data)?):
1138b3068ac3SBenno Lossin                         @data(data),
1139b3068ac3SBenno Lossin                         @slot(slot),
114097de919dSBenno Lossin                         @guards(),
1141b3068ac3SBenno Lossin                         @munch_fields($($fields)*,),
1142b3068ac3SBenno Lossin                     );
1143b3068ac3SBenno Lossin                     // We use unreachable code to ensure that all fields have been mentioned exactly
1144b3068ac3SBenno Lossin                     // once, this struct initializer will still be type-checked and complain with a
1145b3068ac3SBenno Lossin                     // very natural error message if a field is forgotten/mentioned more than once.
1146b3068ac3SBenno Lossin                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
1147b9b88be0SBenno Lossin                     let _ = || {
1148b3068ac3SBenno Lossin                         $crate::__init_internal!(make_initializer:
1149b3068ac3SBenno Lossin                             @slot(slot),
1150b3068ac3SBenno Lossin                             @type_name($t),
1151b3068ac3SBenno Lossin                             @munch_fields($($fields)*,),
1152b3068ac3SBenno Lossin                             @acc(),
1153b3068ac3SBenno Lossin                         );
1154b9b88be0SBenno Lossin                     };
1155b3068ac3SBenno Lossin                 }
1156b3068ac3SBenno Lossin                 Ok(__InitOk)
1157b3068ac3SBenno Lossin             }
1158b3068ac3SBenno Lossin         );
1159b3068ac3SBenno Lossin         let init = move |slot| -> ::core::result::Result<(), $err> {
1160b3068ac3SBenno Lossin             init(slot).map(|__InitOk| ())
1161b3068ac3SBenno Lossin         };
1162b3068ac3SBenno Lossin         let init = unsafe { $crate::init::$construct_closure::<_, $err>(init) };
1163b3068ac3SBenno Lossin         init
1164b3068ac3SBenno Lossin     }};
1165b3068ac3SBenno Lossin     (init_slot($($use_data:ident)?):
1166b3068ac3SBenno Lossin         @data($data:ident),
1167b3068ac3SBenno Lossin         @slot($slot:ident),
116897de919dSBenno Lossin         @guards($($guards:ident,)*),
116935e7fca2SBenno Lossin         @munch_fields($(..Zeroable::zeroed())? $(,)?),
1170b3068ac3SBenno Lossin     ) => {
117197de919dSBenno Lossin         // Endpoint of munching, no fields are left. If execution reaches this point, all fields
117297de919dSBenno Lossin         // have been initialized. Therefore we can now dismiss the guards by forgetting them.
117397de919dSBenno Lossin         $(::core::mem::forget($guards);)*
1174b3068ac3SBenno Lossin     };
1175b3068ac3SBenno Lossin     (init_slot($use_data:ident): // `use_data` is present, so we use the `data` to init fields.
1176b3068ac3SBenno Lossin         @data($data:ident),
1177b3068ac3SBenno Lossin         @slot($slot:ident),
117897de919dSBenno Lossin         @guards($($guards:ident,)*),
1179b3068ac3SBenno Lossin         // In-place initialization syntax.
1180b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1181b3068ac3SBenno Lossin     ) => {
118292fd540dSBenno Lossin         let init = $val;
1183b3068ac3SBenno Lossin         // Call the initializer.
1184b3068ac3SBenno Lossin         //
1185b3068ac3SBenno Lossin         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1186b3068ac3SBenno Lossin         // return when an error/panic occurs.
1187b3068ac3SBenno Lossin         // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
118892fd540dSBenno Lossin         unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), init)? };
118997de919dSBenno Lossin         // Create the drop guard:
1190b3068ac3SBenno Lossin         //
119197de919dSBenno Lossin         // We rely on macro hygiene to make it impossible for users to access this local variable.
119297de919dSBenno Lossin         // We use `paste!` to create new hygiene for `$field`.
119397de919dSBenno Lossin         ::kernel::macros::paste! {
1194b3068ac3SBenno Lossin             // SAFETY: We forget the guard later when initialization has succeeded.
119597de919dSBenno Lossin             let [<$field>] = unsafe {
1196b3068ac3SBenno Lossin                 $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1197b3068ac3SBenno Lossin             };
1198b3068ac3SBenno Lossin 
1199b3068ac3SBenno Lossin             $crate::__init_internal!(init_slot($use_data):
1200b3068ac3SBenno Lossin                 @data($data),
1201b3068ac3SBenno Lossin                 @slot($slot),
120297de919dSBenno Lossin                 @guards([<$field>], $($guards,)*),
1203b3068ac3SBenno Lossin                 @munch_fields($($rest)*),
1204b3068ac3SBenno Lossin             );
120597de919dSBenno Lossin         }
1206b3068ac3SBenno Lossin     };
1207b3068ac3SBenno Lossin     (init_slot(): // No `use_data`, so we use `Init::__init` directly.
1208b3068ac3SBenno Lossin         @data($data:ident),
1209b3068ac3SBenno Lossin         @slot($slot:ident),
121097de919dSBenno Lossin         @guards($($guards:ident,)*),
1211b3068ac3SBenno Lossin         // In-place initialization syntax.
1212b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1213b3068ac3SBenno Lossin     ) => {
121492fd540dSBenno Lossin         let init = $val;
1215b3068ac3SBenno Lossin         // Call the initializer.
1216b3068ac3SBenno Lossin         //
1217b3068ac3SBenno Lossin         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1218b3068ac3SBenno Lossin         // return when an error/panic occurs.
121992fd540dSBenno Lossin         unsafe { $crate::init::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
122097de919dSBenno Lossin         // Create the drop guard:
1221b3068ac3SBenno Lossin         //
122297de919dSBenno Lossin         // We rely on macro hygiene to make it impossible for users to access this local variable.
122397de919dSBenno Lossin         // We use `paste!` to create new hygiene for `$field`.
122497de919dSBenno Lossin         ::kernel::macros::paste! {
1225b3068ac3SBenno Lossin             // SAFETY: We forget the guard later when initialization has succeeded.
122697de919dSBenno Lossin             let [<$field>] = unsafe {
1227b3068ac3SBenno Lossin                 $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1228b3068ac3SBenno Lossin             };
1229b3068ac3SBenno Lossin 
1230b3068ac3SBenno Lossin             $crate::__init_internal!(init_slot():
1231b3068ac3SBenno Lossin                 @data($data),
1232b3068ac3SBenno Lossin                 @slot($slot),
123397de919dSBenno Lossin                 @guards([<$field>], $($guards,)*),
1234b3068ac3SBenno Lossin                 @munch_fields($($rest)*),
1235b3068ac3SBenno Lossin             );
123697de919dSBenno Lossin         }
1237b3068ac3SBenno Lossin     };
1238b3068ac3SBenno Lossin     (init_slot($($use_data:ident)?):
1239b3068ac3SBenno Lossin         @data($data:ident),
1240b3068ac3SBenno Lossin         @slot($slot:ident),
124197de919dSBenno Lossin         @guards($($guards:ident,)*),
1242b3068ac3SBenno Lossin         // Init by-value.
1243b3068ac3SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1244b3068ac3SBenno Lossin     ) => {
124592fd540dSBenno Lossin         {
1246b3068ac3SBenno Lossin             $(let $field = $val;)?
1247b3068ac3SBenno Lossin             // Initialize the field.
1248b3068ac3SBenno Lossin             //
1249b3068ac3SBenno Lossin             // SAFETY: The memory at `slot` is uninitialized.
1250b3068ac3SBenno Lossin             unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
125192fd540dSBenno Lossin         }
1252b3068ac3SBenno Lossin         // Create the drop guard:
1253b3068ac3SBenno Lossin         //
125497de919dSBenno Lossin         // We rely on macro hygiene to make it impossible for users to access this local variable.
125597de919dSBenno Lossin         // We use `paste!` to create new hygiene for `$field`.
125697de919dSBenno Lossin         ::kernel::macros::paste! {
1257b3068ac3SBenno Lossin             // SAFETY: We forget the guard later when initialization has succeeded.
125897de919dSBenno Lossin             let [<$field>] = unsafe {
1259b3068ac3SBenno Lossin                 $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1260b3068ac3SBenno Lossin             };
1261b3068ac3SBenno Lossin 
1262b3068ac3SBenno Lossin             $crate::__init_internal!(init_slot($($use_data)?):
1263b3068ac3SBenno Lossin                 @data($data),
1264b3068ac3SBenno Lossin                 @slot($slot),
126597de919dSBenno Lossin                 @guards([<$field>], $($guards,)*),
1266b3068ac3SBenno Lossin                 @munch_fields($($rest)*),
1267b3068ac3SBenno Lossin             );
126897de919dSBenno Lossin         }
1269b3068ac3SBenno Lossin     };
1270b3068ac3SBenno Lossin     (make_initializer:
1271b3068ac3SBenno Lossin         @slot($slot:ident),
1272674b1c7aSBenno Lossin         @type_name($t:path),
127335e7fca2SBenno Lossin         @munch_fields(..Zeroable::zeroed() $(,)?),
127435e7fca2SBenno Lossin         @acc($($acc:tt)*),
127535e7fca2SBenno Lossin     ) => {
127635e7fca2SBenno Lossin         // Endpoint, nothing more to munch, create the initializer. Since the users specified
127735e7fca2SBenno Lossin         // `..Zeroable::zeroed()`, the slot will already have been zeroed and all field that have
127835e7fca2SBenno Lossin         // not been overwritten are thus zero and initialized. We still check that all fields are
127935e7fca2SBenno Lossin         // actually accessible by using the struct update syntax ourselves.
128035e7fca2SBenno Lossin         // We are inside of a closure that is never executed and thus we can abuse `slot` to
128135e7fca2SBenno Lossin         // get the correct type inference here:
128235e7fca2SBenno Lossin         #[allow(unused_assignments)]
128335e7fca2SBenno Lossin         unsafe {
128435e7fca2SBenno Lossin             let mut zeroed = ::core::mem::zeroed();
128535e7fca2SBenno Lossin             // We have to use type inference here to make zeroed have the correct type. This does
128635e7fca2SBenno Lossin             // not get executed, so it has no effect.
128735e7fca2SBenno Lossin             ::core::ptr::write($slot, zeroed);
128835e7fca2SBenno Lossin             zeroed = ::core::mem::zeroed();
1289674b1c7aSBenno Lossin             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1290674b1c7aSBenno Lossin             // information that is associated to already parsed fragments, so a path fragment
1291674b1c7aSBenno Lossin             // cannot be used in this position. Doing the retokenization results in valid rust
1292674b1c7aSBenno Lossin             // code.
1293674b1c7aSBenno Lossin             ::kernel::macros::paste!(
129435e7fca2SBenno Lossin                 ::core::ptr::write($slot, $t {
129535e7fca2SBenno Lossin                     $($acc)*
129635e7fca2SBenno Lossin                     ..zeroed
129735e7fca2SBenno Lossin                 });
1298674b1c7aSBenno Lossin             );
129935e7fca2SBenno Lossin         }
130035e7fca2SBenno Lossin     };
130135e7fca2SBenno Lossin     (make_initializer:
130235e7fca2SBenno Lossin         @slot($slot:ident),
1303674b1c7aSBenno Lossin         @type_name($t:path),
1304b3068ac3SBenno Lossin         @munch_fields($(,)?),
1305b3068ac3SBenno Lossin         @acc($($acc:tt)*),
1306b3068ac3SBenno Lossin     ) => {
1307b3068ac3SBenno Lossin         // Endpoint, nothing more to munch, create the initializer.
1308b9b88be0SBenno Lossin         // Since we are in the closure that is never called, this will never get executed.
1309b9b88be0SBenno Lossin         // We abuse `slot` to get the correct type inference here:
1310b3068ac3SBenno Lossin         unsafe {
1311674b1c7aSBenno Lossin             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1312674b1c7aSBenno Lossin             // information that is associated to already parsed fragments, so a path fragment
1313674b1c7aSBenno Lossin             // cannot be used in this position. Doing the retokenization results in valid rust
1314674b1c7aSBenno Lossin             // code.
1315674b1c7aSBenno Lossin             ::kernel::macros::paste!(
1316b3068ac3SBenno Lossin                 ::core::ptr::write($slot, $t {
1317b3068ac3SBenno Lossin                     $($acc)*
1318b3068ac3SBenno Lossin                 });
1319674b1c7aSBenno Lossin             );
1320b3068ac3SBenno Lossin         }
1321b3068ac3SBenno Lossin     };
1322b3068ac3SBenno Lossin     (make_initializer:
1323b3068ac3SBenno Lossin         @slot($slot:ident),
1324674b1c7aSBenno Lossin         @type_name($t:path),
1325b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1326b3068ac3SBenno Lossin         @acc($($acc:tt)*),
1327b3068ac3SBenno Lossin     ) => {
1328b3068ac3SBenno Lossin         $crate::__init_internal!(make_initializer:
1329b3068ac3SBenno Lossin             @slot($slot),
1330b3068ac3SBenno Lossin             @type_name($t),
1331b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1332b3068ac3SBenno Lossin             @acc($($acc)* $field: ::core::panic!(),),
1333b3068ac3SBenno Lossin         );
1334b3068ac3SBenno Lossin     };
1335b3068ac3SBenno Lossin     (make_initializer:
1336b3068ac3SBenno Lossin         @slot($slot:ident),
1337674b1c7aSBenno Lossin         @type_name($t:path),
1338b3068ac3SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1339b3068ac3SBenno Lossin         @acc($($acc:tt)*),
1340b3068ac3SBenno Lossin     ) => {
1341b3068ac3SBenno Lossin         $crate::__init_internal!(make_initializer:
1342b3068ac3SBenno Lossin             @slot($slot),
1343b3068ac3SBenno Lossin             @type_name($t),
1344b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1345b3068ac3SBenno Lossin             @acc($($acc)* $field: ::core::panic!(),),
1346b3068ac3SBenno Lossin         );
1347b3068ac3SBenno Lossin     };
1348b3068ac3SBenno Lossin }
1349071cedc8SBenno Lossin 
1350071cedc8SBenno Lossin #[doc(hidden)]
1351071cedc8SBenno Lossin #[macro_export]
1352071cedc8SBenno Lossin macro_rules! __derive_zeroable {
1353071cedc8SBenno Lossin     (parse_input:
1354071cedc8SBenno Lossin         @sig(
1355071cedc8SBenno Lossin             $(#[$($struct_attr:tt)*])*
1356071cedc8SBenno Lossin             $vis:vis struct $name:ident
1357071cedc8SBenno Lossin             $(where $($whr:tt)*)?
1358071cedc8SBenno Lossin         ),
1359071cedc8SBenno Lossin         @impl_generics($($impl_generics:tt)*),
1360071cedc8SBenno Lossin         @ty_generics($($ty_generics:tt)*),
1361071cedc8SBenno Lossin         @body({
1362071cedc8SBenno Lossin             $(
1363071cedc8SBenno Lossin                 $(#[$($field_attr:tt)*])*
1364071cedc8SBenno Lossin                 $field:ident : $field_ty:ty
1365071cedc8SBenno Lossin             ),* $(,)?
1366071cedc8SBenno Lossin         }),
1367071cedc8SBenno Lossin     ) => {
1368071cedc8SBenno Lossin         // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
1369071cedc8SBenno Lossin         #[automatically_derived]
1370071cedc8SBenno Lossin         unsafe impl<$($impl_generics)*> $crate::init::Zeroable for $name<$($ty_generics)*>
1371071cedc8SBenno Lossin         where
1372071cedc8SBenno Lossin             $($($whr)*)?
1373071cedc8SBenno Lossin         {}
1374071cedc8SBenno Lossin         const _: () = {
1375071cedc8SBenno Lossin             fn assert_zeroable<T: ?::core::marker::Sized + $crate::init::Zeroable>() {}
1376071cedc8SBenno Lossin             fn ensure_zeroable<$($impl_generics)*>()
1377071cedc8SBenno Lossin                 where $($($whr)*)?
1378071cedc8SBenno Lossin             {
1379071cedc8SBenno Lossin                 $(assert_zeroable::<$field_ty>();)*
1380071cedc8SBenno Lossin             }
1381071cedc8SBenno Lossin         };
1382071cedc8SBenno Lossin     };
1383071cedc8SBenno Lossin }
1384