xref: /linux/rust/pin-init/src/macros.rs (revision ec7714e4947909190ffb3041a03311a975350fe0)
1fbf8fb32SBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
2fbf8fb32SBenno Lossin 
3fbf8fb32SBenno Lossin //! This module provides the macros that actually implement the proc-macros `pin_data` and
402c01c08SBenno Lossin //! `pinned_drop`. It also contains `__init_internal`, the implementation of the
502c01c08SBenno Lossin //! `{try_}{pin_}init!` macros.
6fbf8fb32SBenno Lossin //!
7fbf8fb32SBenno Lossin //! These macros should never be called directly, since they expect their input to be
8fbf8fb32SBenno Lossin //! in a certain format which is internal. If used incorrectly, these macros can lead to UB even in
9fbf8fb32SBenno Lossin //! safe code! Use the public facing macros instead.
10fbf8fb32SBenno Lossin //!
11fbf8fb32SBenno Lossin //! This architecture has been chosen because the kernel does not yet have access to `syn` which
12fbf8fb32SBenno Lossin //! would make matters a lot easier for implementing these as proc-macros.
13fbf8fb32SBenno Lossin //!
1402c01c08SBenno Lossin //! Since this library and the kernel implementation should diverge as little as possible, the same
1502c01c08SBenno Lossin //! approach has been taken here.
1602c01c08SBenno Lossin //!
17fbf8fb32SBenno Lossin //! # Macro expansion example
18fbf8fb32SBenno Lossin //!
19fbf8fb32SBenno Lossin //! This section is intended for readers trying to understand the macros in this module and the
2002c01c08SBenno Lossin //! `[try_][pin_]init!` macros from `lib.rs`.
21fbf8fb32SBenno Lossin //!
22fbf8fb32SBenno Lossin //! We will look at the following example:
23fbf8fb32SBenno Lossin //!
24fbf8fb32SBenno Lossin //! ```rust,ignore
25fbf8fb32SBenno Lossin //! #[pin_data]
26fbf8fb32SBenno Lossin //! #[repr(C)]
27fbf8fb32SBenno Lossin //! struct Bar<T> {
28fbf8fb32SBenno Lossin //!     #[pin]
29fbf8fb32SBenno Lossin //!     t: T,
30fbf8fb32SBenno Lossin //!     pub x: usize,
31fbf8fb32SBenno Lossin //! }
32fbf8fb32SBenno Lossin //!
33fbf8fb32SBenno Lossin //! impl<T> Bar<T> {
34fbf8fb32SBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
35fbf8fb32SBenno Lossin //!         pin_init!(Self { t, x: 0 })
36fbf8fb32SBenno Lossin //!     }
37fbf8fb32SBenno Lossin //! }
38fbf8fb32SBenno Lossin //!
39fbf8fb32SBenno Lossin //! #[pin_data(PinnedDrop)]
40fbf8fb32SBenno Lossin //! struct Foo {
41fbf8fb32SBenno Lossin //!     a: usize,
42fbf8fb32SBenno Lossin //!     #[pin]
43fbf8fb32SBenno Lossin //!     b: Bar<u32>,
44fbf8fb32SBenno Lossin //! }
45fbf8fb32SBenno Lossin //!
46fbf8fb32SBenno Lossin //! #[pinned_drop]
47fbf8fb32SBenno Lossin //! impl PinnedDrop for Foo {
48fbf8fb32SBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
4902c01c08SBenno Lossin //!         println!("{self:p} is getting dropped.");
50fbf8fb32SBenno Lossin //!     }
51fbf8fb32SBenno Lossin //! }
52fbf8fb32SBenno Lossin //!
53fbf8fb32SBenno Lossin //! let a = 42;
54fbf8fb32SBenno Lossin //! let initializer = pin_init!(Foo {
55fbf8fb32SBenno Lossin //!     a,
56fbf8fb32SBenno Lossin //!     b <- Bar::new(36),
57fbf8fb32SBenno Lossin //! });
58fbf8fb32SBenno Lossin //! ```
59fbf8fb32SBenno Lossin //!
60fbf8fb32SBenno Lossin //! This example includes the most common and important features of the pin-init API.
61fbf8fb32SBenno Lossin //!
62fbf8fb32SBenno Lossin //! Below you can find individual section about the different macro invocations. Here are some
63fbf8fb32SBenno Lossin //! general things we need to take into account when designing macros:
64fbf8fb32SBenno Lossin //! - use global paths, similarly to file paths, these start with the separator: `::core::panic!()`
65fbf8fb32SBenno Lossin //!   this ensures that the correct item is used, since users could define their own `mod core {}`
66fbf8fb32SBenno Lossin //!   and then their own `panic!` inside to execute arbitrary code inside of our macro.
67fbf8fb32SBenno Lossin //! - macro `unsafe` hygiene: we need to ensure that we do not expand arbitrary, user-supplied
68fbf8fb32SBenno Lossin //!   expressions inside of an `unsafe` block in the macro, because this would allow users to do
69fbf8fb32SBenno Lossin //!   `unsafe` operations without an associated `unsafe` block.
70fbf8fb32SBenno Lossin //!
71fbf8fb32SBenno Lossin //! ## `#[pin_data]` on `Bar`
72fbf8fb32SBenno Lossin //!
73fbf8fb32SBenno Lossin //! This macro is used to specify which fields are structurally pinned and which fields are not. It
74fbf8fb32SBenno Lossin //! is placed on the struct definition and allows `#[pin]` to be placed on the fields.
75fbf8fb32SBenno Lossin //!
76fbf8fb32SBenno Lossin //! Here is the definition of `Bar` from our example:
77fbf8fb32SBenno Lossin //!
78fbf8fb32SBenno Lossin //! ```rust,ignore
79fbf8fb32SBenno Lossin //! #[pin_data]
80fbf8fb32SBenno Lossin //! #[repr(C)]
81fbf8fb32SBenno Lossin //! struct Bar<T> {
82fbf8fb32SBenno Lossin //!     #[pin]
83fbf8fb32SBenno Lossin //!     t: T,
84fbf8fb32SBenno Lossin //!     pub x: usize,
85fbf8fb32SBenno Lossin //! }
86fbf8fb32SBenno Lossin //! ```
87fbf8fb32SBenno Lossin //!
88fbf8fb32SBenno Lossin //! This expands to the following code:
89fbf8fb32SBenno Lossin //!
90fbf8fb32SBenno Lossin //! ```rust,ignore
91fbf8fb32SBenno Lossin //! // Firstly the normal definition of the struct, attributes are preserved:
92fbf8fb32SBenno Lossin //! #[repr(C)]
93fbf8fb32SBenno Lossin //! struct Bar<T> {
94fbf8fb32SBenno Lossin //!     t: T,
95fbf8fb32SBenno Lossin //!     pub x: usize,
96fbf8fb32SBenno Lossin //! }
97fbf8fb32SBenno Lossin //! // Then an anonymous constant is defined, this is because we do not want any code to access the
98fbf8fb32SBenno Lossin //! // types that we define inside:
99fbf8fb32SBenno Lossin //! const _: () = {
100fbf8fb32SBenno Lossin //!     // We define the pin-data carrying struct, it is a ZST and needs to have the same generics,
101fbf8fb32SBenno Lossin //!     // since we need to implement access functions for each field and thus need to know its
102fbf8fb32SBenno Lossin //!     // type.
103fbf8fb32SBenno Lossin //!     struct __ThePinData<T> {
104fbf8fb32SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
105fbf8fb32SBenno Lossin //!     }
106fbf8fb32SBenno Lossin //!     // We implement `Copy` for the pin-data struct, since all functions it defines will take
107fbf8fb32SBenno Lossin //!     // `self` by value.
108fbf8fb32SBenno Lossin //!     impl<T> ::core::clone::Clone for __ThePinData<T> {
109fbf8fb32SBenno Lossin //!         fn clone(&self) -> Self {
110fbf8fb32SBenno Lossin //!             *self
111fbf8fb32SBenno Lossin //!         }
112fbf8fb32SBenno Lossin //!     }
113fbf8fb32SBenno Lossin //!     impl<T> ::core::marker::Copy for __ThePinData<T> {}
114fbf8fb32SBenno Lossin //!     // For every field of `Bar`, the pin-data struct will define a function with the same name
115fbf8fb32SBenno Lossin //!     // and accessor (`pub` or `pub(crate)` etc.). This function will take a pointer to the
116fbf8fb32SBenno Lossin //!     // field (`slot`) and a `PinInit` or `Init` depending on the projection kind of the field
117fbf8fb32SBenno Lossin //!     // (if pinning is structural for the field, then `PinInit` otherwise `Init`).
118fbf8fb32SBenno Lossin //!     #[allow(dead_code)]
119fbf8fb32SBenno Lossin //!     impl<T> __ThePinData<T> {
120fbf8fb32SBenno Lossin //!         unsafe fn t<E>(
121fbf8fb32SBenno Lossin //!             self,
122fbf8fb32SBenno Lossin //!             slot: *mut T,
123fbf8fb32SBenno Lossin //!             // Since `t` is `#[pin]`, this is `PinInit`.
124dbd5058bSBenno Lossin //!             init: impl ::pin_init::PinInit<T, E>,
125fbf8fb32SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
126dbd5058bSBenno Lossin //!             unsafe { ::pin_init::PinInit::__pinned_init(init, slot) }
127fbf8fb32SBenno Lossin //!         }
128fbf8fb32SBenno Lossin //!         pub unsafe fn x<E>(
129fbf8fb32SBenno Lossin //!             self,
130fbf8fb32SBenno Lossin //!             slot: *mut usize,
131fbf8fb32SBenno Lossin //!             // Since `x` is not `#[pin]`, this is `Init`.
132dbd5058bSBenno Lossin //!             init: impl ::pin_init::Init<usize, E>,
133fbf8fb32SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
134dbd5058bSBenno Lossin //!             unsafe { ::pin_init::Init::__init(init, slot) }
135fbf8fb32SBenno Lossin //!         }
136fbf8fb32SBenno Lossin //!     }
137fbf8fb32SBenno Lossin //!     // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct
138fbf8fb32SBenno Lossin //!     // that we constructed above.
139dbd5058bSBenno Lossin //!     unsafe impl<T> ::pin_init::__internal::HasPinData for Bar<T> {
140fbf8fb32SBenno Lossin //!         type PinData = __ThePinData<T>;
141fbf8fb32SBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
142fbf8fb32SBenno Lossin //!             __ThePinData {
143fbf8fb32SBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
144fbf8fb32SBenno Lossin //!             }
145fbf8fb32SBenno Lossin //!         }
146fbf8fb32SBenno Lossin //!     }
147fbf8fb32SBenno Lossin //!     // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data
148fbf8fb32SBenno Lossin //!     // struct. This is important to ensure that no user can implement a rogue `__pin_data`
149fbf8fb32SBenno Lossin //!     // function without using `unsafe`.
150dbd5058bSBenno Lossin //!     unsafe impl<T> ::pin_init::__internal::PinData for __ThePinData<T> {
151fbf8fb32SBenno Lossin //!         type Datee = Bar<T>;
152fbf8fb32SBenno Lossin //!     }
153fbf8fb32SBenno Lossin //!     // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is
154fbf8fb32SBenno Lossin //!     // `Unpin`. In other words, whether `Bar` is `Unpin` only depends on structurally pinned
155fbf8fb32SBenno Lossin //!     // fields (those marked with `#[pin]`). These fields will be listed in this struct, in our
156fbf8fb32SBenno Lossin //!     // case no such fields exist, hence this is almost empty. The two phantomdata fields exist
157fbf8fb32SBenno Lossin //!     // for two reasons:
158fbf8fb32SBenno Lossin //!     // - `__phantom`: every generic must be used, since we cannot really know which generics
159fbf8fb32SBenno Lossin //!     //   are used, we declare all and then use everything here once.
160fbf8fb32SBenno Lossin //!     // - `__phantom_pin`: uses the `'__pin` lifetime and ensures that this struct is invariant
161fbf8fb32SBenno Lossin //!     //   over it. The lifetime is needed to work around the limitation that trait bounds must
162fbf8fb32SBenno Lossin //!     //   not be trivial, e.g. the user has a `#[pin] PhantomPinned` field -- this is
163fbf8fb32SBenno Lossin //!     //   unconditionally `!Unpin` and results in an error. The lifetime tricks the compiler
164fbf8fb32SBenno Lossin //!     //   into accepting these bounds regardless.
165fbf8fb32SBenno Lossin //!     #[allow(dead_code)]
166fbf8fb32SBenno Lossin //!     struct __Unpin<'__pin, T> {
167fbf8fb32SBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
168fbf8fb32SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
169fbf8fb32SBenno Lossin //!         // Our only `#[pin]` field is `t`.
170fbf8fb32SBenno Lossin //!         t: T,
171fbf8fb32SBenno Lossin //!     }
172fbf8fb32SBenno Lossin //!     #[doc(hidden)]
173fbf8fb32SBenno Lossin //!     impl<'__pin, T> ::core::marker::Unpin for Bar<T>
174fbf8fb32SBenno Lossin //!     where
175fbf8fb32SBenno Lossin //!         __Unpin<'__pin, T>: ::core::marker::Unpin,
176fbf8fb32SBenno Lossin //!     {}
177fbf8fb32SBenno Lossin //!     // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
178fbf8fb32SBenno Lossin //!     // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
179fbf8fb32SBenno Lossin //!     // UB with only safe code, so we disallow this by giving a trait implementation error using
180fbf8fb32SBenno Lossin //!     // a direct impl and a blanket implementation.
181fbf8fb32SBenno Lossin //!     trait MustNotImplDrop {}
182fbf8fb32SBenno Lossin //!     // Normally `Drop` bounds do not have the correct semantics, but for this purpose they do
183fbf8fb32SBenno Lossin //!     // (normally people want to know if a type has any kind of drop glue at all, here we want
184fbf8fb32SBenno Lossin //!     // to know if it has any kind of custom drop glue, which is exactly what this bound does).
185fbf8fb32SBenno Lossin //!     #[expect(drop_bounds)]
186fbf8fb32SBenno Lossin //!     impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
187fbf8fb32SBenno Lossin //!     impl<T> MustNotImplDrop for Bar<T> {}
188fbf8fb32SBenno Lossin //!     // Here comes a convenience check, if one implemented `PinnedDrop`, but forgot to add it to
189fbf8fb32SBenno Lossin //!     // `#[pin_data]`, then this will error with the same mechanic as above, this is not needed
190fbf8fb32SBenno Lossin //!     // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`.
191fbf8fb32SBenno Lossin //!     #[expect(non_camel_case_types)]
192fbf8fb32SBenno Lossin //!     trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
193fbf8fb32SBenno Lossin //!     impl<
194dbd5058bSBenno Lossin //!         T: ::pin_init::PinnedDrop,
195fbf8fb32SBenno Lossin //!     > UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
196fbf8fb32SBenno Lossin //!     impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
197fbf8fb32SBenno Lossin //! };
198fbf8fb32SBenno Lossin //! ```
199fbf8fb32SBenno Lossin //!
200fbf8fb32SBenno Lossin //! ## `pin_init!` in `impl Bar`
201fbf8fb32SBenno Lossin //!
202fbf8fb32SBenno Lossin //! This macro creates an pin-initializer for the given struct. It requires that the struct is
203fbf8fb32SBenno Lossin //! annotated by `#[pin_data]`.
204fbf8fb32SBenno Lossin //!
205fbf8fb32SBenno Lossin //! Here is the impl on `Bar` defining the new function:
206fbf8fb32SBenno Lossin //!
207fbf8fb32SBenno Lossin //! ```rust,ignore
208fbf8fb32SBenno Lossin //! impl<T> Bar<T> {
209fbf8fb32SBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
210fbf8fb32SBenno Lossin //!         pin_init!(Self { t, x: 0 })
211fbf8fb32SBenno Lossin //!     }
212fbf8fb32SBenno Lossin //! }
213fbf8fb32SBenno Lossin //! ```
214fbf8fb32SBenno Lossin //!
215fbf8fb32SBenno Lossin //! This expands to the following code:
216fbf8fb32SBenno Lossin //!
217fbf8fb32SBenno Lossin //! ```rust,ignore
218fbf8fb32SBenno Lossin //! impl<T> Bar<T> {
219fbf8fb32SBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
220fbf8fb32SBenno Lossin //!         {
221fbf8fb32SBenno Lossin //!             // We do not want to allow arbitrary returns, so we declare this type as the `Ok`
222fbf8fb32SBenno Lossin //!             // return type and shadow it later when we insert the arbitrary user code. That way
223fbf8fb32SBenno Lossin //!             // there will be no possibility of returning without `unsafe`.
224fbf8fb32SBenno Lossin //!             struct __InitOk;
225fbf8fb32SBenno Lossin //!             // Get the data about fields from the supplied type.
226fbf8fb32SBenno Lossin //!             // - the function is unsafe, hence the unsafe block
227fbf8fb32SBenno Lossin //!             // - we `use` the `HasPinData` trait in the block, it is only available in that
228fbf8fb32SBenno Lossin //!             //   scope.
229fbf8fb32SBenno Lossin //!             let data = unsafe {
230dbd5058bSBenno Lossin //!                 use ::pin_init::__internal::HasPinData;
231fbf8fb32SBenno Lossin //!                 Self::__pin_data()
232fbf8fb32SBenno Lossin //!             };
233fbf8fb32SBenno Lossin //!             // Ensure that `data` really is of type `PinData` and help with type inference:
234dbd5058bSBenno Lossin //!             let init = ::pin_init::__internal::PinData::make_closure::<
235fbf8fb32SBenno Lossin //!                 _,
236fbf8fb32SBenno Lossin //!                 __InitOk,
237fbf8fb32SBenno Lossin //!                 ::core::convert::Infallible,
238fbf8fb32SBenno Lossin //!             >(data, move |slot| {
239fbf8fb32SBenno Lossin //!                 {
240fbf8fb32SBenno Lossin //!                     // Shadow the structure so it cannot be used to return early. If a user
241fbf8fb32SBenno Lossin //!                     // tries to write `return Ok(__InitOk)`, then they get a type error,
242fbf8fb32SBenno Lossin //!                     // since that will refer to this struct instead of the one defined
243fbf8fb32SBenno Lossin //!                     // above.
244fbf8fb32SBenno Lossin //!                     struct __InitOk;
245fbf8fb32SBenno Lossin //!                     // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
246fbf8fb32SBenno Lossin //!                     {
247fbf8fb32SBenno Lossin //!                         unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) };
248fbf8fb32SBenno Lossin //!                     }
249fbf8fb32SBenno Lossin //!                     // Since initialization could fail later (not in this case, since the
250fbf8fb32SBenno Lossin //!                     // error type is `Infallible`) we will need to drop this field if there
251fbf8fb32SBenno Lossin //!                     // is an error later. This `DropGuard` will drop the field when it gets
252fbf8fb32SBenno Lossin //!                     // dropped and has not yet been forgotten.
253fbf8fb32SBenno Lossin //!                     let __t_guard = unsafe {
25402c01c08SBenno Lossin //!                         ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).t))
255fbf8fb32SBenno Lossin //!                     };
256fbf8fb32SBenno Lossin //!                     // Expansion of `x: 0,`:
257fbf8fb32SBenno Lossin //!                     // Since this can be an arbitrary expression we cannot place it inside
258fbf8fb32SBenno Lossin //!                     // of the `unsafe` block, so we bind it here.
259fbf8fb32SBenno Lossin //!                     {
260fbf8fb32SBenno Lossin //!                         let x = 0;
261fbf8fb32SBenno Lossin //!                         unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
262fbf8fb32SBenno Lossin //!                     }
263fbf8fb32SBenno Lossin //!                     // We again create a `DropGuard`.
264fbf8fb32SBenno Lossin //!                     let __x_guard = unsafe {
265dbd5058bSBenno Lossin //!                         ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).x))
266fbf8fb32SBenno Lossin //!                     };
267fbf8fb32SBenno Lossin //!                     // Since initialization has successfully completed, we can now forget
268fbf8fb32SBenno Lossin //!                     // the guards. This is not `mem::forget`, since we only have
269fbf8fb32SBenno Lossin //!                     // `&DropGuard`.
270fbf8fb32SBenno Lossin //!                     ::core::mem::forget(__x_guard);
271fbf8fb32SBenno Lossin //!                     ::core::mem::forget(__t_guard);
272fbf8fb32SBenno Lossin //!                     // Here we use the type checker to ensure that every field has been
273fbf8fb32SBenno Lossin //!                     // initialized exactly once, since this is `if false` it will never get
274fbf8fb32SBenno Lossin //!                     // executed, but still type-checked.
275fbf8fb32SBenno Lossin //!                     // Additionally we abuse `slot` to automatically infer the correct type
276fbf8fb32SBenno Lossin //!                     // for the struct. This is also another check that every field is
277fbf8fb32SBenno Lossin //!                     // accessible from this scope.
278fbf8fb32SBenno Lossin //!                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
279fbf8fb32SBenno Lossin //!                     let _ = || {
280fbf8fb32SBenno Lossin //!                         unsafe {
281fbf8fb32SBenno Lossin //!                             ::core::ptr::write(
282fbf8fb32SBenno Lossin //!                                 slot,
283fbf8fb32SBenno Lossin //!                                 Self {
284fbf8fb32SBenno Lossin //!                                     // We only care about typecheck finding every field
285fbf8fb32SBenno Lossin //!                                     // here, the expression does not matter, just conjure
286fbf8fb32SBenno Lossin //!                                     // one using `panic!()`:
287fbf8fb32SBenno Lossin //!                                     t: ::core::panic!(),
288fbf8fb32SBenno Lossin //!                                     x: ::core::panic!(),
289fbf8fb32SBenno Lossin //!                                 },
290fbf8fb32SBenno Lossin //!                             );
291fbf8fb32SBenno Lossin //!                         };
292fbf8fb32SBenno Lossin //!                     };
293fbf8fb32SBenno Lossin //!                 }
294fbf8fb32SBenno Lossin //!                 // We leave the scope above and gain access to the previously shadowed
295fbf8fb32SBenno Lossin //!                 // `__InitOk` that we need to return.
296fbf8fb32SBenno Lossin //!                 Ok(__InitOk)
297fbf8fb32SBenno Lossin //!             });
298fbf8fb32SBenno Lossin //!             // Change the return type from `__InitOk` to `()`.
299fbf8fb32SBenno Lossin //!             let init = move |
300fbf8fb32SBenno Lossin //!                 slot,
301fbf8fb32SBenno Lossin //!             | -> ::core::result::Result<(), ::core::convert::Infallible> {
302fbf8fb32SBenno Lossin //!                 init(slot).map(|__InitOk| ())
303fbf8fb32SBenno Lossin //!             };
304fbf8fb32SBenno Lossin //!             // Construct the initializer.
305fbf8fb32SBenno Lossin //!             let init = unsafe {
306dbd5058bSBenno Lossin //!                 ::pin_init::pin_init_from_closure::<
307fbf8fb32SBenno Lossin //!                     _,
308fbf8fb32SBenno Lossin //!                     ::core::convert::Infallible,
309fbf8fb32SBenno Lossin //!                 >(init)
310fbf8fb32SBenno Lossin //!             };
311fbf8fb32SBenno Lossin //!             init
312fbf8fb32SBenno Lossin //!         }
313fbf8fb32SBenno Lossin //!     }
314fbf8fb32SBenno Lossin //! }
315fbf8fb32SBenno Lossin //! ```
316fbf8fb32SBenno Lossin //!
317fbf8fb32SBenno Lossin //! ## `#[pin_data]` on `Foo`
318fbf8fb32SBenno Lossin //!
319fbf8fb32SBenno Lossin //! Since we already took a look at `#[pin_data]` on `Bar`, this section will only explain the
320fbf8fb32SBenno Lossin //! differences/new things in the expansion of the `Foo` definition:
321fbf8fb32SBenno Lossin //!
322fbf8fb32SBenno Lossin //! ```rust,ignore
323fbf8fb32SBenno Lossin //! #[pin_data(PinnedDrop)]
324fbf8fb32SBenno Lossin //! struct Foo {
325fbf8fb32SBenno Lossin //!     a: usize,
326fbf8fb32SBenno Lossin //!     #[pin]
327fbf8fb32SBenno Lossin //!     b: Bar<u32>,
328fbf8fb32SBenno Lossin //! }
329fbf8fb32SBenno Lossin //! ```
330fbf8fb32SBenno Lossin //!
331fbf8fb32SBenno Lossin //! This expands to the following code:
332fbf8fb32SBenno Lossin //!
333fbf8fb32SBenno Lossin //! ```rust,ignore
334fbf8fb32SBenno Lossin //! struct Foo {
335fbf8fb32SBenno Lossin //!     a: usize,
336fbf8fb32SBenno Lossin //!     b: Bar<u32>,
337fbf8fb32SBenno Lossin //! }
338fbf8fb32SBenno Lossin //! const _: () = {
339fbf8fb32SBenno Lossin //!     struct __ThePinData {
340fbf8fb32SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
341fbf8fb32SBenno Lossin //!     }
342fbf8fb32SBenno Lossin //!     impl ::core::clone::Clone for __ThePinData {
343fbf8fb32SBenno Lossin //!         fn clone(&self) -> Self {
344fbf8fb32SBenno Lossin //!             *self
345fbf8fb32SBenno Lossin //!         }
346fbf8fb32SBenno Lossin //!     }
347fbf8fb32SBenno Lossin //!     impl ::core::marker::Copy for __ThePinData {}
348fbf8fb32SBenno Lossin //!     #[allow(dead_code)]
349fbf8fb32SBenno Lossin //!     impl __ThePinData {
350fbf8fb32SBenno Lossin //!         unsafe fn b<E>(
351fbf8fb32SBenno Lossin //!             self,
352fbf8fb32SBenno Lossin //!             slot: *mut Bar<u32>,
353dbd5058bSBenno Lossin //!             init: impl ::pin_init::PinInit<Bar<u32>, E>,
354fbf8fb32SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
355dbd5058bSBenno Lossin //!             unsafe { ::pin_init::PinInit::__pinned_init(init, slot) }
356fbf8fb32SBenno Lossin //!         }
357fbf8fb32SBenno Lossin //!         unsafe fn a<E>(
358fbf8fb32SBenno Lossin //!             self,
359fbf8fb32SBenno Lossin //!             slot: *mut usize,
360dbd5058bSBenno Lossin //!             init: impl ::pin_init::Init<usize, E>,
361fbf8fb32SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
362dbd5058bSBenno Lossin //!             unsafe { ::pin_init::Init::__init(init, slot) }
363fbf8fb32SBenno Lossin //!         }
364fbf8fb32SBenno Lossin //!     }
365dbd5058bSBenno Lossin //!     unsafe impl ::pin_init::__internal::HasPinData for Foo {
366fbf8fb32SBenno Lossin //!         type PinData = __ThePinData;
367fbf8fb32SBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
368fbf8fb32SBenno Lossin //!             __ThePinData {
369fbf8fb32SBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
370fbf8fb32SBenno Lossin //!             }
371fbf8fb32SBenno Lossin //!         }
372fbf8fb32SBenno Lossin //!     }
373dbd5058bSBenno Lossin //!     unsafe impl ::pin_init::__internal::PinData for __ThePinData {
374fbf8fb32SBenno Lossin //!         type Datee = Foo;
375fbf8fb32SBenno Lossin //!     }
376fbf8fb32SBenno Lossin //!     #[allow(dead_code)]
377fbf8fb32SBenno Lossin //!     struct __Unpin<'__pin> {
378fbf8fb32SBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
379fbf8fb32SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
380fbf8fb32SBenno Lossin //!         b: Bar<u32>,
381fbf8fb32SBenno Lossin //!     }
382fbf8fb32SBenno Lossin //!     #[doc(hidden)]
383fbf8fb32SBenno Lossin //!     impl<'__pin> ::core::marker::Unpin for Foo
384fbf8fb32SBenno Lossin //!     where
385fbf8fb32SBenno Lossin //!         __Unpin<'__pin>: ::core::marker::Unpin,
386fbf8fb32SBenno Lossin //!     {}
387fbf8fb32SBenno Lossin //!     // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to
388fbf8fb32SBenno Lossin //!     // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
389fbf8fb32SBenno Lossin //!     // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
390fbf8fb32SBenno Lossin //!     impl ::core::ops::Drop for Foo {
391fbf8fb32SBenno Lossin //!         fn drop(&mut self) {
392fbf8fb32SBenno Lossin //!             // Since we are getting dropped, no one else has a reference to `self` and thus we
393fbf8fb32SBenno Lossin //!             // can assume that we never move.
394fbf8fb32SBenno Lossin //!             let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
395fbf8fb32SBenno Lossin //!             // Create the unsafe token that proves that we are inside of a destructor, this
396fbf8fb32SBenno Lossin //!             // type is only allowed to be created in a destructor.
397dbd5058bSBenno Lossin //!             let token = unsafe { ::pin_init::__internal::OnlyCallFromDrop::new() };
398dbd5058bSBenno Lossin //!             ::pin_init::PinnedDrop::drop(pinned, token);
399fbf8fb32SBenno Lossin //!         }
400fbf8fb32SBenno Lossin //!     }
401fbf8fb32SBenno Lossin //! };
402fbf8fb32SBenno Lossin //! ```
403fbf8fb32SBenno Lossin //!
404fbf8fb32SBenno Lossin //! ## `#[pinned_drop]` on `impl PinnedDrop for Foo`
405fbf8fb32SBenno Lossin //!
406fbf8fb32SBenno Lossin //! This macro is used to implement the `PinnedDrop` trait, since that trait is `unsafe` and has an
407fbf8fb32SBenno Lossin //! extra parameter that should not be used at all. The macro hides that parameter.
408fbf8fb32SBenno Lossin //!
409fbf8fb32SBenno Lossin //! Here is the `PinnedDrop` impl for `Foo`:
410fbf8fb32SBenno Lossin //!
411fbf8fb32SBenno Lossin //! ```rust,ignore
412fbf8fb32SBenno Lossin //! #[pinned_drop]
413fbf8fb32SBenno Lossin //! impl PinnedDrop for Foo {
414fbf8fb32SBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
41502c01c08SBenno Lossin //!         println!("{self:p} is getting dropped.");
416fbf8fb32SBenno Lossin //!     }
417fbf8fb32SBenno Lossin //! }
418fbf8fb32SBenno Lossin //! ```
419fbf8fb32SBenno Lossin //!
420fbf8fb32SBenno Lossin //! This expands to the following code:
421fbf8fb32SBenno Lossin //!
422fbf8fb32SBenno Lossin //! ```rust,ignore
423fbf8fb32SBenno Lossin //! // `unsafe`, full path and the token parameter are added, everything else stays the same.
424dbd5058bSBenno Lossin //! unsafe impl ::pin_init::PinnedDrop for Foo {
425dbd5058bSBenno Lossin //!     fn drop(self: Pin<&mut Self>, _: ::pin_init::__internal::OnlyCallFromDrop) {
42602c01c08SBenno Lossin //!         println!("{self:p} is getting dropped.");
427fbf8fb32SBenno Lossin //!     }
428fbf8fb32SBenno Lossin //! }
429fbf8fb32SBenno Lossin //! ```
430fbf8fb32SBenno Lossin //!
431fbf8fb32SBenno Lossin //! ## `pin_init!` on `Foo`
432fbf8fb32SBenno Lossin //!
433fbf8fb32SBenno Lossin //! Since we already took a look at `pin_init!` on `Bar`, this section will only show the expansion
434fbf8fb32SBenno Lossin //! of `pin_init!` on `Foo`:
435fbf8fb32SBenno Lossin //!
436fbf8fb32SBenno Lossin //! ```rust,ignore
437fbf8fb32SBenno Lossin //! let a = 42;
438fbf8fb32SBenno Lossin //! let initializer = pin_init!(Foo {
439fbf8fb32SBenno Lossin //!     a,
440fbf8fb32SBenno Lossin //!     b <- Bar::new(36),
441fbf8fb32SBenno Lossin //! });
442fbf8fb32SBenno Lossin //! ```
443fbf8fb32SBenno Lossin //!
444fbf8fb32SBenno Lossin //! This expands to the following code:
445fbf8fb32SBenno Lossin //!
446fbf8fb32SBenno Lossin //! ```rust,ignore
447fbf8fb32SBenno Lossin //! let a = 42;
448fbf8fb32SBenno Lossin //! let initializer = {
449fbf8fb32SBenno Lossin //!     struct __InitOk;
450fbf8fb32SBenno Lossin //!     let data = unsafe {
451dbd5058bSBenno Lossin //!         use ::pin_init::__internal::HasPinData;
452fbf8fb32SBenno Lossin //!         Foo::__pin_data()
453fbf8fb32SBenno Lossin //!     };
454dbd5058bSBenno Lossin //!     let init = ::pin_init::__internal::PinData::make_closure::<
455fbf8fb32SBenno Lossin //!         _,
456fbf8fb32SBenno Lossin //!         __InitOk,
457fbf8fb32SBenno Lossin //!         ::core::convert::Infallible,
458fbf8fb32SBenno Lossin //!     >(data, move |slot| {
459fbf8fb32SBenno Lossin //!         {
460fbf8fb32SBenno Lossin //!             struct __InitOk;
461fbf8fb32SBenno Lossin //!             {
462fbf8fb32SBenno Lossin //!                 unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
463fbf8fb32SBenno Lossin //!             }
464fbf8fb32SBenno Lossin //!             let __a_guard = unsafe {
465dbd5058bSBenno Lossin //!                 ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
466fbf8fb32SBenno Lossin //!             };
467fbf8fb32SBenno Lossin //!             let init = Bar::new(36);
468fbf8fb32SBenno Lossin //!             unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
469fbf8fb32SBenno Lossin //!             let __b_guard = unsafe {
470dbd5058bSBenno Lossin //!                 ::pin_init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
471fbf8fb32SBenno Lossin //!             };
472fbf8fb32SBenno Lossin //!             ::core::mem::forget(__b_guard);
473fbf8fb32SBenno Lossin //!             ::core::mem::forget(__a_guard);
474fbf8fb32SBenno Lossin //!             #[allow(unreachable_code, clippy::diverging_sub_expression)]
475fbf8fb32SBenno Lossin //!             let _ = || {
476fbf8fb32SBenno Lossin //!                 unsafe {
477fbf8fb32SBenno Lossin //!                     ::core::ptr::write(
478fbf8fb32SBenno Lossin //!                         slot,
479fbf8fb32SBenno Lossin //!                         Foo {
480fbf8fb32SBenno Lossin //!                             a: ::core::panic!(),
481fbf8fb32SBenno Lossin //!                             b: ::core::panic!(),
482fbf8fb32SBenno Lossin //!                         },
483fbf8fb32SBenno Lossin //!                     );
484fbf8fb32SBenno Lossin //!                 };
485fbf8fb32SBenno Lossin //!             };
486fbf8fb32SBenno Lossin //!         }
487fbf8fb32SBenno Lossin //!         Ok(__InitOk)
488fbf8fb32SBenno Lossin //!     });
489fbf8fb32SBenno Lossin //!     let init = move |
490fbf8fb32SBenno Lossin //!         slot,
491fbf8fb32SBenno Lossin //!     | -> ::core::result::Result<(), ::core::convert::Infallible> {
492fbf8fb32SBenno Lossin //!         init(slot).map(|__InitOk| ())
493fbf8fb32SBenno Lossin //!     };
494fbf8fb32SBenno Lossin //!     let init = unsafe {
495dbd5058bSBenno Lossin //!         ::pin_init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
496fbf8fb32SBenno Lossin //!     };
497fbf8fb32SBenno Lossin //!     init
498fbf8fb32SBenno Lossin //! };
499fbf8fb32SBenno Lossin //! ```
500fbf8fb32SBenno Lossin 
501dbd5058bSBenno Lossin #[cfg(kernel)]
502b321b938SBenno Lossin pub use ::macros::paste;
503dbd5058bSBenno Lossin #[cfg(not(kernel))]
504dbd5058bSBenno Lossin pub use ::paste::paste;
505b321b938SBenno Lossin 
506fbf8fb32SBenno Lossin /// Creates a `unsafe impl<...> PinnedDrop for $type` block.
507fbf8fb32SBenno Lossin ///
508fbf8fb32SBenno Lossin /// See [`PinnedDrop`] for more information.
509fbf8fb32SBenno Lossin #[doc(hidden)]
510fbf8fb32SBenno Lossin #[macro_export]
511fbf8fb32SBenno Lossin macro_rules! __pinned_drop {
512fbf8fb32SBenno Lossin     (
513fbf8fb32SBenno Lossin         @impl_sig($($impl_sig:tt)*),
514fbf8fb32SBenno Lossin         @impl_body(
515fbf8fb32SBenno Lossin             $(#[$($attr:tt)*])*
516fbf8fb32SBenno Lossin             fn drop($($sig:tt)*) {
517fbf8fb32SBenno Lossin                 $($inner:tt)*
518fbf8fb32SBenno Lossin             }
519fbf8fb32SBenno Lossin         ),
520fbf8fb32SBenno Lossin     ) => {
521fbf8fb32SBenno Lossin         // SAFETY: TODO.
522fbf8fb32SBenno Lossin         unsafe $($impl_sig)* {
523fbf8fb32SBenno Lossin             // Inherit all attributes and the type/ident tokens for the signature.
524fbf8fb32SBenno Lossin             $(#[$($attr)*])*
525dbd5058bSBenno Lossin             fn drop($($sig)*, _: $crate::__internal::OnlyCallFromDrop) {
526fbf8fb32SBenno Lossin                 $($inner)*
527fbf8fb32SBenno Lossin             }
528fbf8fb32SBenno Lossin         }
529fbf8fb32SBenno Lossin     }
530fbf8fb32SBenno Lossin }
531fbf8fb32SBenno Lossin 
532fbf8fb32SBenno Lossin /// This macro first parses the struct definition such that it separates pinned and not pinned
533fbf8fb32SBenno Lossin /// fields. Afterwards it declares the struct and implement the `PinData` trait safely.
534fbf8fb32SBenno Lossin #[doc(hidden)]
535fbf8fb32SBenno Lossin #[macro_export]
536fbf8fb32SBenno Lossin macro_rules! __pin_data {
537fbf8fb32SBenno Lossin     // Proc-macro entry point, this is supplied by the proc-macro pre-parsing.
538fbf8fb32SBenno Lossin     (parse_input:
539fbf8fb32SBenno Lossin         @args($($pinned_drop:ident)?),
540fbf8fb32SBenno Lossin         @sig(
541fbf8fb32SBenno Lossin             $(#[$($struct_attr:tt)*])*
542fbf8fb32SBenno Lossin             $vis:vis struct $name:ident
543fbf8fb32SBenno Lossin             $(where $($whr:tt)*)?
544fbf8fb32SBenno Lossin         ),
545fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
546fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
547fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
548fbf8fb32SBenno Lossin         @body({ $($fields:tt)* }),
549fbf8fb32SBenno Lossin     ) => {
550fbf8fb32SBenno Lossin         // We now use token munching to iterate through all of the fields. While doing this we
551fbf8fb32SBenno Lossin         // identify fields marked with `#[pin]`, these fields are the 'pinned fields'. The user
552fbf8fb32SBenno Lossin         // wants these to be structurally pinned. The rest of the fields are the
553fbf8fb32SBenno Lossin         // 'not pinned fields'. Additionally we collect all fields, since we need them in the right
554fbf8fb32SBenno Lossin         // order to declare the struct.
555fbf8fb32SBenno Lossin         //
556fbf8fb32SBenno Lossin         // In this call we also put some explaining comments for the parameters.
557fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
558fbf8fb32SBenno Lossin             // Attributes on the struct itself, these will just be propagated to be put onto the
559fbf8fb32SBenno Lossin             // struct definition.
560fbf8fb32SBenno Lossin             @struct_attrs($(#[$($struct_attr)*])*),
561fbf8fb32SBenno Lossin             // The visibility of the struct.
562fbf8fb32SBenno Lossin             @vis($vis),
563fbf8fb32SBenno Lossin             // The name of the struct.
564fbf8fb32SBenno Lossin             @name($name),
565fbf8fb32SBenno Lossin             // The 'impl generics', the generics that will need to be specified on the struct inside
566fbf8fb32SBenno Lossin             // of an `impl<$ty_generics>` block.
567fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
568fbf8fb32SBenno Lossin             // The 'ty generics', the generics that will need to be specified on the impl blocks.
569fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
570fbf8fb32SBenno Lossin             // The 'decl generics', the generics that need to be specified on the struct
571fbf8fb32SBenno Lossin             // definition.
572fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
573fbf8fb32SBenno Lossin             // The where clause of any impl block and the declaration.
574fbf8fb32SBenno Lossin             @where($($($whr)*)?),
575fbf8fb32SBenno Lossin             // The remaining fields tokens that need to be processed.
576fbf8fb32SBenno Lossin             // We add a `,` at the end to ensure correct parsing.
577fbf8fb32SBenno Lossin             @fields_munch($($fields)* ,),
578fbf8fb32SBenno Lossin             // The pinned fields.
579fbf8fb32SBenno Lossin             @pinned(),
580fbf8fb32SBenno Lossin             // The not pinned fields.
581fbf8fb32SBenno Lossin             @not_pinned(),
582fbf8fb32SBenno Lossin             // All fields.
583fbf8fb32SBenno Lossin             @fields(),
584fbf8fb32SBenno Lossin             // The accumulator containing all attributes already parsed.
585fbf8fb32SBenno Lossin             @accum(),
586fbf8fb32SBenno Lossin             // Contains `yes` or `` to indicate if `#[pin]` was found on the current field.
587fbf8fb32SBenno Lossin             @is_pinned(),
588fbf8fb32SBenno Lossin             // The proc-macro argument, this should be `PinnedDrop` or ``.
589fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
590fbf8fb32SBenno Lossin         );
591fbf8fb32SBenno Lossin     };
592fbf8fb32SBenno Lossin     (find_pinned_fields:
593fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
594fbf8fb32SBenno Lossin         @vis($vis:vis),
595fbf8fb32SBenno Lossin         @name($name:ident),
596fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
597fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
598fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
599fbf8fb32SBenno Lossin         @where($($whr:tt)*),
600fbf8fb32SBenno Lossin         // We found a PhantomPinned field, this should generally be pinned!
601fbf8fb32SBenno Lossin         @fields_munch($field:ident : $($($(::)?core::)?marker::)?PhantomPinned, $($rest:tt)*),
602fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
603fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
604fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
605fbf8fb32SBenno Lossin         @accum($($accum:tt)*),
606fbf8fb32SBenno Lossin         // This field is not pinned.
607fbf8fb32SBenno Lossin         @is_pinned(),
608fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
609fbf8fb32SBenno Lossin     ) => {
610fbf8fb32SBenno Lossin         ::core::compile_error!(concat!(
611fbf8fb32SBenno Lossin             "The field `",
612fbf8fb32SBenno Lossin             stringify!($field),
613fbf8fb32SBenno Lossin             "` of type `PhantomPinned` only has an effect, if it has the `#[pin]` attribute.",
614fbf8fb32SBenno Lossin         ));
615fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
616fbf8fb32SBenno Lossin             @struct_attrs($($struct_attrs)*),
617fbf8fb32SBenno Lossin             @vis($vis),
618fbf8fb32SBenno Lossin             @name($name),
619fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
620fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
621fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
622fbf8fb32SBenno Lossin             @where($($whr)*),
623fbf8fb32SBenno Lossin             @fields_munch($($rest)*),
624fbf8fb32SBenno Lossin             @pinned($($pinned)* $($accum)* $field: ::core::marker::PhantomPinned,),
625fbf8fb32SBenno Lossin             @not_pinned($($not_pinned)*),
626fbf8fb32SBenno Lossin             @fields($($fields)* $($accum)* $field: ::core::marker::PhantomPinned,),
627fbf8fb32SBenno Lossin             @accum(),
628fbf8fb32SBenno Lossin             @is_pinned(),
629fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
630fbf8fb32SBenno Lossin         );
631fbf8fb32SBenno Lossin     };
632fbf8fb32SBenno Lossin     (find_pinned_fields:
633fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
634fbf8fb32SBenno Lossin         @vis($vis:vis),
635fbf8fb32SBenno Lossin         @name($name:ident),
636fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
637fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
638fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
639fbf8fb32SBenno Lossin         @where($($whr:tt)*),
640fbf8fb32SBenno Lossin         // We reached the field declaration.
641fbf8fb32SBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
642fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
643fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
644fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
645fbf8fb32SBenno Lossin         @accum($($accum:tt)*),
646fbf8fb32SBenno Lossin         // This field is pinned.
647fbf8fb32SBenno Lossin         @is_pinned(yes),
648fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
649fbf8fb32SBenno Lossin     ) => {
650fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
651fbf8fb32SBenno Lossin             @struct_attrs($($struct_attrs)*),
652fbf8fb32SBenno Lossin             @vis($vis),
653fbf8fb32SBenno Lossin             @name($name),
654fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
655fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
656fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
657fbf8fb32SBenno Lossin             @where($($whr)*),
658fbf8fb32SBenno Lossin             @fields_munch($($rest)*),
659fbf8fb32SBenno Lossin             @pinned($($pinned)* $($accum)* $field: $type,),
660fbf8fb32SBenno Lossin             @not_pinned($($not_pinned)*),
661fbf8fb32SBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
662fbf8fb32SBenno Lossin             @accum(),
663fbf8fb32SBenno Lossin             @is_pinned(),
664fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
665fbf8fb32SBenno Lossin         );
666fbf8fb32SBenno Lossin     };
667fbf8fb32SBenno Lossin     (find_pinned_fields:
668fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
669fbf8fb32SBenno Lossin         @vis($vis:vis),
670fbf8fb32SBenno Lossin         @name($name:ident),
671fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
672fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
673fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
674fbf8fb32SBenno Lossin         @where($($whr:tt)*),
675fbf8fb32SBenno Lossin         // We reached the field declaration.
676fbf8fb32SBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
677fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
678fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
679fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
680fbf8fb32SBenno Lossin         @accum($($accum:tt)*),
681fbf8fb32SBenno Lossin         // This field is not pinned.
682fbf8fb32SBenno Lossin         @is_pinned(),
683fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
684fbf8fb32SBenno Lossin     ) => {
685fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
686fbf8fb32SBenno Lossin             @struct_attrs($($struct_attrs)*),
687fbf8fb32SBenno Lossin             @vis($vis),
688fbf8fb32SBenno Lossin             @name($name),
689fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
690fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
691fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
692fbf8fb32SBenno Lossin             @where($($whr)*),
693fbf8fb32SBenno Lossin             @fields_munch($($rest)*),
694fbf8fb32SBenno Lossin             @pinned($($pinned)*),
695fbf8fb32SBenno Lossin             @not_pinned($($not_pinned)* $($accum)* $field: $type,),
696fbf8fb32SBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
697fbf8fb32SBenno Lossin             @accum(),
698fbf8fb32SBenno Lossin             @is_pinned(),
699fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
700fbf8fb32SBenno Lossin         );
701fbf8fb32SBenno Lossin     };
702fbf8fb32SBenno Lossin     (find_pinned_fields:
703fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
704fbf8fb32SBenno Lossin         @vis($vis:vis),
705fbf8fb32SBenno Lossin         @name($name:ident),
706fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
707fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
708fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
709fbf8fb32SBenno Lossin         @where($($whr:tt)*),
710fbf8fb32SBenno Lossin         // We found the `#[pin]` attr.
711fbf8fb32SBenno Lossin         @fields_munch(#[pin] $($rest:tt)*),
712fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
713fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
714fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
715fbf8fb32SBenno Lossin         @accum($($accum:tt)*),
716fbf8fb32SBenno Lossin         @is_pinned($($is_pinned:ident)?),
717fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
718fbf8fb32SBenno Lossin     ) => {
719fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
720fbf8fb32SBenno Lossin             @struct_attrs($($struct_attrs)*),
721fbf8fb32SBenno Lossin             @vis($vis),
722fbf8fb32SBenno Lossin             @name($name),
723fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
724fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
725fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
726fbf8fb32SBenno Lossin             @where($($whr)*),
727fbf8fb32SBenno Lossin             @fields_munch($($rest)*),
728fbf8fb32SBenno Lossin             // We do not include `#[pin]` in the list of attributes, since it is not actually an
729fbf8fb32SBenno Lossin             // attribute that is defined somewhere.
730fbf8fb32SBenno Lossin             @pinned($($pinned)*),
731fbf8fb32SBenno Lossin             @not_pinned($($not_pinned)*),
732fbf8fb32SBenno Lossin             @fields($($fields)*),
733fbf8fb32SBenno Lossin             @accum($($accum)*),
734fbf8fb32SBenno Lossin             // Set this to `yes`.
735fbf8fb32SBenno Lossin             @is_pinned(yes),
736fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
737fbf8fb32SBenno Lossin         );
738fbf8fb32SBenno Lossin     };
739fbf8fb32SBenno Lossin     (find_pinned_fields:
740fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
741fbf8fb32SBenno Lossin         @vis($vis:vis),
742fbf8fb32SBenno Lossin         @name($name:ident),
743fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
744fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
745fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
746fbf8fb32SBenno Lossin         @where($($whr:tt)*),
747fbf8fb32SBenno Lossin         // We reached the field declaration with visibility, for simplicity we only munch the
748fbf8fb32SBenno Lossin         // visibility and put it into `$accum`.
749fbf8fb32SBenno Lossin         @fields_munch($fvis:vis $field:ident $($rest:tt)*),
750fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
751fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
752fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
753fbf8fb32SBenno Lossin         @accum($($accum:tt)*),
754fbf8fb32SBenno Lossin         @is_pinned($($is_pinned:ident)?),
755fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
756fbf8fb32SBenno Lossin     ) => {
757fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
758fbf8fb32SBenno Lossin             @struct_attrs($($struct_attrs)*),
759fbf8fb32SBenno Lossin             @vis($vis),
760fbf8fb32SBenno Lossin             @name($name),
761fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
762fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
763fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
764fbf8fb32SBenno Lossin             @where($($whr)*),
765fbf8fb32SBenno Lossin             @fields_munch($field $($rest)*),
766fbf8fb32SBenno Lossin             @pinned($($pinned)*),
767fbf8fb32SBenno Lossin             @not_pinned($($not_pinned)*),
768fbf8fb32SBenno Lossin             @fields($($fields)*),
769fbf8fb32SBenno Lossin             @accum($($accum)* $fvis),
770fbf8fb32SBenno Lossin             @is_pinned($($is_pinned)?),
771fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
772fbf8fb32SBenno Lossin         );
773fbf8fb32SBenno Lossin     };
774fbf8fb32SBenno Lossin     (find_pinned_fields:
775fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
776fbf8fb32SBenno Lossin         @vis($vis:vis),
777fbf8fb32SBenno Lossin         @name($name:ident),
778fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
779fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
780fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
781fbf8fb32SBenno Lossin         @where($($whr:tt)*),
782fbf8fb32SBenno Lossin         // Some other attribute, just put it into `$accum`.
783fbf8fb32SBenno Lossin         @fields_munch(#[$($attr:tt)*] $($rest:tt)*),
784fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
785fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
786fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
787fbf8fb32SBenno Lossin         @accum($($accum:tt)*),
788fbf8fb32SBenno Lossin         @is_pinned($($is_pinned:ident)?),
789fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
790fbf8fb32SBenno Lossin     ) => {
791fbf8fb32SBenno Lossin         $crate::__pin_data!(find_pinned_fields:
792fbf8fb32SBenno Lossin             @struct_attrs($($struct_attrs)*),
793fbf8fb32SBenno Lossin             @vis($vis),
794fbf8fb32SBenno Lossin             @name($name),
795fbf8fb32SBenno Lossin             @impl_generics($($impl_generics)*),
796fbf8fb32SBenno Lossin             @ty_generics($($ty_generics)*),
797fbf8fb32SBenno Lossin             @decl_generics($($decl_generics)*),
798fbf8fb32SBenno Lossin             @where($($whr)*),
799fbf8fb32SBenno Lossin             @fields_munch($($rest)*),
800fbf8fb32SBenno Lossin             @pinned($($pinned)*),
801fbf8fb32SBenno Lossin             @not_pinned($($not_pinned)*),
802fbf8fb32SBenno Lossin             @fields($($fields)*),
803fbf8fb32SBenno Lossin             @accum($($accum)* #[$($attr)*]),
804fbf8fb32SBenno Lossin             @is_pinned($($is_pinned)?),
805fbf8fb32SBenno Lossin             @pinned_drop($($pinned_drop)?),
806fbf8fb32SBenno Lossin         );
807fbf8fb32SBenno Lossin     };
808fbf8fb32SBenno Lossin     (find_pinned_fields:
809fbf8fb32SBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
810fbf8fb32SBenno Lossin         @vis($vis:vis),
811fbf8fb32SBenno Lossin         @name($name:ident),
812fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
813fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
814fbf8fb32SBenno Lossin         @decl_generics($($decl_generics:tt)*),
815fbf8fb32SBenno Lossin         @where($($whr:tt)*),
816fbf8fb32SBenno Lossin         // We reached the end of the fields, plus an optional additional comma, since we added one
817fbf8fb32SBenno Lossin         // before and the user is also allowed to put a trailing comma.
818fbf8fb32SBenno Lossin         @fields_munch($(,)?),
819fbf8fb32SBenno Lossin         @pinned($($pinned:tt)*),
820fbf8fb32SBenno Lossin         @not_pinned($($not_pinned:tt)*),
821fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
822fbf8fb32SBenno Lossin         @accum(),
823fbf8fb32SBenno Lossin         @is_pinned(),
824fbf8fb32SBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
825fbf8fb32SBenno Lossin     ) => {
826fbf8fb32SBenno Lossin         // Declare the struct with all fields in the correct order.
827fbf8fb32SBenno Lossin         $($struct_attrs)*
828fbf8fb32SBenno Lossin         $vis struct $name <$($decl_generics)*>
829fbf8fb32SBenno Lossin         where $($whr)*
830fbf8fb32SBenno Lossin         {
831fbf8fb32SBenno Lossin             $($fields)*
832fbf8fb32SBenno Lossin         }
833fbf8fb32SBenno Lossin 
834fbf8fb32SBenno Lossin         // We put the rest into this const item, because it then will not be accessible to anything
835fbf8fb32SBenno Lossin         // outside.
836fbf8fb32SBenno Lossin         const _: () = {
837fbf8fb32SBenno Lossin             // We declare this struct which will host all of the projection function for our type.
838fbf8fb32SBenno Lossin             // it will be invariant over all generic parameters which are inherited from the
839fbf8fb32SBenno Lossin             // struct.
840fbf8fb32SBenno Lossin             $vis struct __ThePinData<$($impl_generics)*>
841fbf8fb32SBenno Lossin             where $($whr)*
842fbf8fb32SBenno Lossin             {
843fbf8fb32SBenno Lossin                 __phantom: ::core::marker::PhantomData<
844fbf8fb32SBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
845fbf8fb32SBenno Lossin                 >,
846fbf8fb32SBenno Lossin             }
847fbf8fb32SBenno Lossin 
848fbf8fb32SBenno Lossin             impl<$($impl_generics)*> ::core::clone::Clone for __ThePinData<$($ty_generics)*>
849fbf8fb32SBenno Lossin             where $($whr)*
850fbf8fb32SBenno Lossin             {
851fbf8fb32SBenno Lossin                 fn clone(&self) -> Self { *self }
852fbf8fb32SBenno Lossin             }
853fbf8fb32SBenno Lossin 
854fbf8fb32SBenno Lossin             impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*>
855fbf8fb32SBenno Lossin             where $($whr)*
856fbf8fb32SBenno Lossin             {}
857fbf8fb32SBenno Lossin 
858fbf8fb32SBenno Lossin             // Make all projection functions.
859fbf8fb32SBenno Lossin             $crate::__pin_data!(make_pin_data:
860fbf8fb32SBenno Lossin                 @pin_data(__ThePinData),
861fbf8fb32SBenno Lossin                 @impl_generics($($impl_generics)*),
862fbf8fb32SBenno Lossin                 @ty_generics($($ty_generics)*),
863fbf8fb32SBenno Lossin                 @where($($whr)*),
864fbf8fb32SBenno Lossin                 @pinned($($pinned)*),
865fbf8fb32SBenno Lossin                 @not_pinned($($not_pinned)*),
866fbf8fb32SBenno Lossin             );
867fbf8fb32SBenno Lossin 
868fbf8fb32SBenno Lossin             // SAFETY: We have added the correct projection functions above to `__ThePinData` and
869fbf8fb32SBenno Lossin             // we also use the least restrictive generics possible.
870fbf8fb32SBenno Lossin             unsafe impl<$($impl_generics)*>
871dbd5058bSBenno Lossin                 $crate::__internal::HasPinData for $name<$($ty_generics)*>
872fbf8fb32SBenno Lossin             where $($whr)*
873fbf8fb32SBenno Lossin             {
874fbf8fb32SBenno Lossin                 type PinData = __ThePinData<$($ty_generics)*>;
875fbf8fb32SBenno Lossin 
876fbf8fb32SBenno Lossin                 unsafe fn __pin_data() -> Self::PinData {
877fbf8fb32SBenno Lossin                     __ThePinData { __phantom: ::core::marker::PhantomData }
878fbf8fb32SBenno Lossin                 }
879fbf8fb32SBenno Lossin             }
880fbf8fb32SBenno Lossin 
881fbf8fb32SBenno Lossin             // SAFETY: TODO.
882fbf8fb32SBenno Lossin             unsafe impl<$($impl_generics)*>
883dbd5058bSBenno Lossin                 $crate::__internal::PinData for __ThePinData<$($ty_generics)*>
884fbf8fb32SBenno Lossin             where $($whr)*
885fbf8fb32SBenno Lossin             {
886fbf8fb32SBenno Lossin                 type Datee = $name<$($ty_generics)*>;
887fbf8fb32SBenno Lossin             }
888fbf8fb32SBenno Lossin 
889fbf8fb32SBenno Lossin             // This struct will be used for the unpin analysis. Since only structurally pinned
890fbf8fb32SBenno Lossin             // fields are relevant whether the struct should implement `Unpin`.
891fbf8fb32SBenno Lossin             #[allow(dead_code)]
892fbf8fb32SBenno Lossin             struct __Unpin <'__pin, $($impl_generics)*>
893fbf8fb32SBenno Lossin             where $($whr)*
894fbf8fb32SBenno Lossin             {
895fbf8fb32SBenno Lossin                 __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
896fbf8fb32SBenno Lossin                 __phantom: ::core::marker::PhantomData<
897fbf8fb32SBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
898fbf8fb32SBenno Lossin                 >,
899fbf8fb32SBenno Lossin                 // Only the pinned fields.
900fbf8fb32SBenno Lossin                 $($pinned)*
901fbf8fb32SBenno Lossin             }
902fbf8fb32SBenno Lossin 
903fbf8fb32SBenno Lossin             #[doc(hidden)]
904fbf8fb32SBenno Lossin             impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*>
905fbf8fb32SBenno Lossin             where
906fbf8fb32SBenno Lossin                 __Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin,
907fbf8fb32SBenno Lossin                 $($whr)*
908fbf8fb32SBenno Lossin             {}
909fbf8fb32SBenno Lossin 
910fbf8fb32SBenno Lossin             // We need to disallow normal `Drop` implementation, the exact behavior depends on
911fbf8fb32SBenno Lossin             // whether `PinnedDrop` was specified as the parameter.
912fbf8fb32SBenno Lossin             $crate::__pin_data!(drop_prevention:
913fbf8fb32SBenno Lossin                 @name($name),
914fbf8fb32SBenno Lossin                 @impl_generics($($impl_generics)*),
915fbf8fb32SBenno Lossin                 @ty_generics($($ty_generics)*),
916fbf8fb32SBenno Lossin                 @where($($whr)*),
917fbf8fb32SBenno Lossin                 @pinned_drop($($pinned_drop)?),
918fbf8fb32SBenno Lossin             );
919fbf8fb32SBenno Lossin         };
920fbf8fb32SBenno Lossin     };
921fbf8fb32SBenno Lossin     // When no `PinnedDrop` was specified, then we have to prevent implementing drop.
922fbf8fb32SBenno Lossin     (drop_prevention:
923fbf8fb32SBenno Lossin         @name($name:ident),
924fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
925fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
926fbf8fb32SBenno Lossin         @where($($whr:tt)*),
927fbf8fb32SBenno Lossin         @pinned_drop(),
928fbf8fb32SBenno Lossin     ) => {
929fbf8fb32SBenno Lossin         // We prevent this by creating a trait that will be implemented for all types implementing
930fbf8fb32SBenno Lossin         // `Drop`. Additionally we will implement this trait for the struct leading to a conflict,
931fbf8fb32SBenno Lossin         // if it also implements `Drop`
932fbf8fb32SBenno Lossin         trait MustNotImplDrop {}
933fbf8fb32SBenno Lossin         #[expect(drop_bounds)]
934fbf8fb32SBenno Lossin         impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
935fbf8fb32SBenno Lossin         impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*>
936fbf8fb32SBenno Lossin         where $($whr)* {}
937fbf8fb32SBenno Lossin         // We also take care to prevent users from writing a useless `PinnedDrop` implementation.
938fbf8fb32SBenno Lossin         // They might implement `PinnedDrop` correctly for the struct, but forget to give
939fbf8fb32SBenno Lossin         // `PinnedDrop` as the parameter to `#[pin_data]`.
940fbf8fb32SBenno Lossin         #[expect(non_camel_case_types)]
941fbf8fb32SBenno Lossin         trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
942dbd5058bSBenno Lossin         impl<T: $crate::PinnedDrop>
943fbf8fb32SBenno Lossin             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
944fbf8fb32SBenno Lossin         impl<$($impl_generics)*>
945fbf8fb32SBenno Lossin             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for $name<$($ty_generics)*>
946fbf8fb32SBenno Lossin         where $($whr)* {}
947fbf8fb32SBenno Lossin     };
948fbf8fb32SBenno Lossin     // When `PinnedDrop` was specified we just implement `Drop` and delegate.
949fbf8fb32SBenno Lossin     (drop_prevention:
950fbf8fb32SBenno Lossin         @name($name:ident),
951fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
952fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
953fbf8fb32SBenno Lossin         @where($($whr:tt)*),
954fbf8fb32SBenno Lossin         @pinned_drop(PinnedDrop),
955fbf8fb32SBenno Lossin     ) => {
956fbf8fb32SBenno Lossin         impl<$($impl_generics)*> ::core::ops::Drop for $name<$($ty_generics)*>
957fbf8fb32SBenno Lossin         where $($whr)*
958fbf8fb32SBenno Lossin         {
959fbf8fb32SBenno Lossin             fn drop(&mut self) {
960fbf8fb32SBenno Lossin                 // SAFETY: Since this is a destructor, `self` will not move after this function
961fbf8fb32SBenno Lossin                 // terminates, since it is inaccessible.
962fbf8fb32SBenno Lossin                 let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
963fbf8fb32SBenno Lossin                 // SAFETY: Since this is a drop function, we can create this token to call the
964fbf8fb32SBenno Lossin                 // pinned destructor of this type.
965dbd5058bSBenno Lossin                 let token = unsafe { $crate::__internal::OnlyCallFromDrop::new() };
966dbd5058bSBenno Lossin                 $crate::PinnedDrop::drop(pinned, token);
967fbf8fb32SBenno Lossin             }
968fbf8fb32SBenno Lossin         }
969fbf8fb32SBenno Lossin     };
970fbf8fb32SBenno Lossin     // If some other parameter was specified, we emit a readable error.
971fbf8fb32SBenno Lossin     (drop_prevention:
972fbf8fb32SBenno Lossin         @name($name:ident),
973fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
974fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
975fbf8fb32SBenno Lossin         @where($($whr:tt)*),
976fbf8fb32SBenno Lossin         @pinned_drop($($rest:tt)*),
977fbf8fb32SBenno Lossin     ) => {
978fbf8fb32SBenno Lossin         compile_error!(
979fbf8fb32SBenno Lossin             "Wrong parameters to `#[pin_data]`, expected nothing or `PinnedDrop`, got '{}'.",
980fbf8fb32SBenno Lossin             stringify!($($rest)*),
981fbf8fb32SBenno Lossin         );
982fbf8fb32SBenno Lossin     };
983fbf8fb32SBenno Lossin     (make_pin_data:
984fbf8fb32SBenno Lossin         @pin_data($pin_data:ident),
985fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
986fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
987fbf8fb32SBenno Lossin         @where($($whr:tt)*),
988fbf8fb32SBenno Lossin         @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
989fbf8fb32SBenno Lossin         @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
990fbf8fb32SBenno Lossin     ) => {
991fbf8fb32SBenno Lossin         // For every field, we create a projection function according to its projection type. If a
992fbf8fb32SBenno Lossin         // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
993fbf8fb32SBenno Lossin         // structurally pinned, then it can be initialized via `Init`.
994fbf8fb32SBenno Lossin         //
995fbf8fb32SBenno Lossin         // The functions are `unsafe` to prevent accidentally calling them.
996fbf8fb32SBenno Lossin         #[allow(dead_code)]
997fbf8fb32SBenno Lossin         #[expect(clippy::missing_safety_doc)]
998fbf8fb32SBenno Lossin         impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
999fbf8fb32SBenno Lossin         where $($whr)*
1000fbf8fb32SBenno Lossin         {
1001fbf8fb32SBenno Lossin             $(
1002fbf8fb32SBenno Lossin                 $(#[$($p_attr)*])*
1003fbf8fb32SBenno Lossin                 $pvis unsafe fn $p_field<E>(
1004fbf8fb32SBenno Lossin                     self,
1005fbf8fb32SBenno Lossin                     slot: *mut $p_type,
1006dbd5058bSBenno Lossin                     init: impl $crate::PinInit<$p_type, E>,
1007fbf8fb32SBenno Lossin                 ) -> ::core::result::Result<(), E> {
1008fbf8fb32SBenno Lossin                     // SAFETY: TODO.
1009dbd5058bSBenno Lossin                     unsafe { $crate::PinInit::__pinned_init(init, slot) }
1010fbf8fb32SBenno Lossin                 }
1011fbf8fb32SBenno Lossin             )*
1012fbf8fb32SBenno Lossin             $(
1013fbf8fb32SBenno Lossin                 $(#[$($attr)*])*
1014fbf8fb32SBenno Lossin                 $fvis unsafe fn $field<E>(
1015fbf8fb32SBenno Lossin                     self,
1016fbf8fb32SBenno Lossin                     slot: *mut $type,
1017dbd5058bSBenno Lossin                     init: impl $crate::Init<$type, E>,
1018fbf8fb32SBenno Lossin                 ) -> ::core::result::Result<(), E> {
1019fbf8fb32SBenno Lossin                     // SAFETY: TODO.
1020dbd5058bSBenno Lossin                     unsafe { $crate::Init::__init(init, slot) }
1021fbf8fb32SBenno Lossin                 }
1022fbf8fb32SBenno Lossin             )*
1023fbf8fb32SBenno Lossin         }
1024fbf8fb32SBenno Lossin     };
1025fbf8fb32SBenno Lossin }
1026fbf8fb32SBenno Lossin 
1027fbf8fb32SBenno Lossin /// The internal init macro. Do not call manually!
1028fbf8fb32SBenno Lossin ///
1029fbf8fb32SBenno Lossin /// This is called by the `{try_}{pin_}init!` macros with various inputs.
1030fbf8fb32SBenno Lossin ///
1031fbf8fb32SBenno Lossin /// This macro has multiple internal call configurations, these are always the very first ident:
1032fbf8fb32SBenno Lossin /// - nothing: this is the base case and called by the `{try_}{pin_}init!` macros.
1033fbf8fb32SBenno Lossin /// - `with_update_parsed`: when the `..Zeroable::zeroed()` syntax has been handled.
1034fbf8fb32SBenno Lossin /// - `init_slot`: recursively creates the code that initializes all fields in `slot`.
1035fbf8fb32SBenno Lossin /// - `make_initializer`: recursively create the struct initializer that guarantees that every
1036fbf8fb32SBenno Lossin ///   field has been initialized exactly once.
1037fbf8fb32SBenno Lossin #[doc(hidden)]
1038fbf8fb32SBenno Lossin #[macro_export]
1039fbf8fb32SBenno Lossin macro_rules! __init_internal {
1040fbf8fb32SBenno Lossin     (
1041fbf8fb32SBenno Lossin         @this($($this:ident)?),
1042fbf8fb32SBenno Lossin         @typ($t:path),
1043fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
1044fbf8fb32SBenno Lossin         @error($err:ty),
1045fbf8fb32SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
1046fbf8fb32SBenno Lossin         // case.
1047fbf8fb32SBenno Lossin         @data($data:ident, $($use_data:ident)?),
1048fbf8fb32SBenno Lossin         // `HasPinData` or `HasInitData`.
1049fbf8fb32SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
1050fbf8fb32SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
1051fbf8fb32SBenno Lossin         @construct_closure($construct_closure:ident),
1052fbf8fb32SBenno Lossin         @munch_fields(),
1053fbf8fb32SBenno Lossin     ) => {
1054fbf8fb32SBenno Lossin         $crate::__init_internal!(with_update_parsed:
1055fbf8fb32SBenno Lossin             @this($($this)?),
1056fbf8fb32SBenno Lossin             @typ($t),
1057fbf8fb32SBenno Lossin             @fields($($fields)*),
1058fbf8fb32SBenno Lossin             @error($err),
1059fbf8fb32SBenno Lossin             @data($data, $($use_data)?),
1060fbf8fb32SBenno Lossin             @has_data($has_data, $get_data),
1061fbf8fb32SBenno Lossin             @construct_closure($construct_closure),
1062fbf8fb32SBenno Lossin             @zeroed(), // Nothing means default behavior.
1063fbf8fb32SBenno Lossin         )
1064fbf8fb32SBenno Lossin     };
1065fbf8fb32SBenno Lossin     (
1066fbf8fb32SBenno Lossin         @this($($this:ident)?),
1067fbf8fb32SBenno Lossin         @typ($t:path),
1068fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
1069fbf8fb32SBenno Lossin         @error($err:ty),
1070fbf8fb32SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
1071fbf8fb32SBenno Lossin         // case.
1072fbf8fb32SBenno Lossin         @data($data:ident, $($use_data:ident)?),
1073fbf8fb32SBenno Lossin         // `HasPinData` or `HasInitData`.
1074fbf8fb32SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
1075fbf8fb32SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
1076fbf8fb32SBenno Lossin         @construct_closure($construct_closure:ident),
1077fbf8fb32SBenno Lossin         @munch_fields(..Zeroable::zeroed()),
1078fbf8fb32SBenno Lossin     ) => {
1079fbf8fb32SBenno Lossin         $crate::__init_internal!(with_update_parsed:
1080fbf8fb32SBenno Lossin             @this($($this)?),
1081fbf8fb32SBenno Lossin             @typ($t),
1082fbf8fb32SBenno Lossin             @fields($($fields)*),
1083fbf8fb32SBenno Lossin             @error($err),
1084fbf8fb32SBenno Lossin             @data($data, $($use_data)?),
1085fbf8fb32SBenno Lossin             @has_data($has_data, $get_data),
1086fbf8fb32SBenno Lossin             @construct_closure($construct_closure),
1087fbf8fb32SBenno Lossin             @zeroed(()), // `()` means zero all fields not mentioned.
1088fbf8fb32SBenno Lossin         )
1089fbf8fb32SBenno Lossin     };
1090fbf8fb32SBenno Lossin     (
1091fbf8fb32SBenno Lossin         @this($($this:ident)?),
1092fbf8fb32SBenno Lossin         @typ($t:path),
1093fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
1094fbf8fb32SBenno Lossin         @error($err:ty),
1095fbf8fb32SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
1096fbf8fb32SBenno Lossin         // case.
1097fbf8fb32SBenno Lossin         @data($data:ident, $($use_data:ident)?),
1098fbf8fb32SBenno Lossin         // `HasPinData` or `HasInitData`.
1099fbf8fb32SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
1100fbf8fb32SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
1101fbf8fb32SBenno Lossin         @construct_closure($construct_closure:ident),
1102fbf8fb32SBenno Lossin         @munch_fields($ignore:tt $($rest:tt)*),
1103fbf8fb32SBenno Lossin     ) => {
1104fbf8fb32SBenno Lossin         $crate::__init_internal!(
1105fbf8fb32SBenno Lossin             @this($($this)?),
1106fbf8fb32SBenno Lossin             @typ($t),
1107fbf8fb32SBenno Lossin             @fields($($fields)*),
1108fbf8fb32SBenno Lossin             @error($err),
1109fbf8fb32SBenno Lossin             @data($data, $($use_data)?),
1110fbf8fb32SBenno Lossin             @has_data($has_data, $get_data),
1111fbf8fb32SBenno Lossin             @construct_closure($construct_closure),
1112fbf8fb32SBenno Lossin             @munch_fields($($rest)*),
1113fbf8fb32SBenno Lossin         )
1114fbf8fb32SBenno Lossin     };
1115fbf8fb32SBenno Lossin     (with_update_parsed:
1116fbf8fb32SBenno Lossin         @this($($this:ident)?),
1117fbf8fb32SBenno Lossin         @typ($t:path),
1118fbf8fb32SBenno Lossin         @fields($($fields:tt)*),
1119fbf8fb32SBenno Lossin         @error($err:ty),
1120fbf8fb32SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
1121fbf8fb32SBenno Lossin         // case.
1122fbf8fb32SBenno Lossin         @data($data:ident, $($use_data:ident)?),
1123fbf8fb32SBenno Lossin         // `HasPinData` or `HasInitData`.
1124fbf8fb32SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
1125fbf8fb32SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
1126fbf8fb32SBenno Lossin         @construct_closure($construct_closure:ident),
1127fbf8fb32SBenno Lossin         @zeroed($($init_zeroed:expr)?),
1128fbf8fb32SBenno Lossin     ) => {{
1129fbf8fb32SBenno Lossin         // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
1130fbf8fb32SBenno Lossin         // type and shadow it later when we insert the arbitrary user code. That way there will be
1131fbf8fb32SBenno Lossin         // no possibility of returning without `unsafe`.
1132fbf8fb32SBenno Lossin         struct __InitOk;
1133fbf8fb32SBenno Lossin         // Get the data about fields from the supplied type.
1134fbf8fb32SBenno Lossin         //
1135fbf8fb32SBenno Lossin         // SAFETY: TODO.
1136fbf8fb32SBenno Lossin         let data = unsafe {
1137dbd5058bSBenno Lossin             use $crate::__internal::$has_data;
1138fbf8fb32SBenno Lossin             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1139fbf8fb32SBenno Lossin             // information that is associated to already parsed fragments, so a path fragment
1140fbf8fb32SBenno Lossin             // cannot be used in this position. Doing the retokenization results in valid rust
1141fbf8fb32SBenno Lossin             // code.
1142dbd5058bSBenno Lossin             $crate::macros::paste!($t::$get_data())
1143fbf8fb32SBenno Lossin         };
1144fbf8fb32SBenno Lossin         // Ensure that `data` really is of type `$data` and help with type inference:
1145dbd5058bSBenno Lossin         let init = $crate::__internal::$data::make_closure::<_, __InitOk, $err>(
1146fbf8fb32SBenno Lossin             data,
1147fbf8fb32SBenno Lossin             move |slot| {
1148fbf8fb32SBenno Lossin                 {
1149fbf8fb32SBenno Lossin                     // Shadow the structure so it cannot be used to return early.
1150fbf8fb32SBenno Lossin                     struct __InitOk;
1151fbf8fb32SBenno Lossin                     // If `$init_zeroed` is present we should zero the slot now and not emit an
1152fbf8fb32SBenno Lossin                     // error when fields are missing (since they will be zeroed). We also have to
1153fbf8fb32SBenno Lossin                     // check that the type actually implements `Zeroable`.
1154fbf8fb32SBenno Lossin                     $({
1155dbd5058bSBenno Lossin                         fn assert_zeroable<T: $crate::Zeroable>(_: *mut T) {}
1156fbf8fb32SBenno Lossin                         // Ensure that the struct is indeed `Zeroable`.
1157fbf8fb32SBenno Lossin                         assert_zeroable(slot);
1158fbf8fb32SBenno Lossin                         // SAFETY: The type implements `Zeroable` by the check above.
1159fbf8fb32SBenno Lossin                         unsafe { ::core::ptr::write_bytes(slot, 0, 1) };
1160fbf8fb32SBenno Lossin                         $init_zeroed // This will be `()` if set.
1161fbf8fb32SBenno Lossin                     })?
1162fbf8fb32SBenno Lossin                     // Create the `this` so it can be referenced by the user inside of the
1163fbf8fb32SBenno Lossin                     // expressions creating the individual fields.
1164fbf8fb32SBenno Lossin                     $(let $this = unsafe { ::core::ptr::NonNull::new_unchecked(slot) };)?
1165fbf8fb32SBenno Lossin                     // Initialize every field.
1166fbf8fb32SBenno Lossin                     $crate::__init_internal!(init_slot($($use_data)?):
1167fbf8fb32SBenno Lossin                         @data(data),
1168fbf8fb32SBenno Lossin                         @slot(slot),
1169fbf8fb32SBenno Lossin                         @guards(),
1170fbf8fb32SBenno Lossin                         @munch_fields($($fields)*,),
1171fbf8fb32SBenno Lossin                     );
1172fbf8fb32SBenno Lossin                     // We use unreachable code to ensure that all fields have been mentioned exactly
1173fbf8fb32SBenno Lossin                     // once, this struct initializer will still be type-checked and complain with a
1174fbf8fb32SBenno Lossin                     // very natural error message if a field is forgotten/mentioned more than once.
1175fbf8fb32SBenno Lossin                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
1176fbf8fb32SBenno Lossin                     let _ = || {
1177fbf8fb32SBenno Lossin                         $crate::__init_internal!(make_initializer:
1178fbf8fb32SBenno Lossin                             @slot(slot),
1179fbf8fb32SBenno Lossin                             @type_name($t),
1180fbf8fb32SBenno Lossin                             @munch_fields($($fields)*,),
1181fbf8fb32SBenno Lossin                             @acc(),
1182fbf8fb32SBenno Lossin                         );
1183fbf8fb32SBenno Lossin                     };
1184fbf8fb32SBenno Lossin                 }
1185fbf8fb32SBenno Lossin                 Ok(__InitOk)
1186fbf8fb32SBenno Lossin             }
1187fbf8fb32SBenno Lossin         );
1188fbf8fb32SBenno Lossin         let init = move |slot| -> ::core::result::Result<(), $err> {
1189fbf8fb32SBenno Lossin             init(slot).map(|__InitOk| ())
1190fbf8fb32SBenno Lossin         };
1191fbf8fb32SBenno Lossin         // SAFETY: TODO.
1192dbd5058bSBenno Lossin         let init = unsafe { $crate::$construct_closure::<_, $err>(init) };
1193fbf8fb32SBenno Lossin         init
1194fbf8fb32SBenno Lossin     }};
1195fbf8fb32SBenno Lossin     (init_slot($($use_data:ident)?):
1196fbf8fb32SBenno Lossin         @data($data:ident),
1197fbf8fb32SBenno Lossin         @slot($slot:ident),
1198fbf8fb32SBenno Lossin         @guards($($guards:ident,)*),
1199fbf8fb32SBenno Lossin         @munch_fields($(..Zeroable::zeroed())? $(,)?),
1200fbf8fb32SBenno Lossin     ) => {
1201fbf8fb32SBenno Lossin         // Endpoint of munching, no fields are left. If execution reaches this point, all fields
1202fbf8fb32SBenno Lossin         // have been initialized. Therefore we can now dismiss the guards by forgetting them.
1203fbf8fb32SBenno Lossin         $(::core::mem::forget($guards);)*
1204fbf8fb32SBenno Lossin     };
1205fbf8fb32SBenno Lossin     (init_slot($use_data:ident): // `use_data` is present, so we use the `data` to init fields.
1206fbf8fb32SBenno Lossin         @data($data:ident),
1207fbf8fb32SBenno Lossin         @slot($slot:ident),
1208fbf8fb32SBenno Lossin         @guards($($guards:ident,)*),
1209fbf8fb32SBenno Lossin         // In-place initialization syntax.
1210fbf8fb32SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1211fbf8fb32SBenno Lossin     ) => {
1212fbf8fb32SBenno Lossin         let init = $val;
1213fbf8fb32SBenno Lossin         // Call the initializer.
1214fbf8fb32SBenno Lossin         //
1215fbf8fb32SBenno Lossin         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1216fbf8fb32SBenno Lossin         // return when an error/panic occurs.
1217fbf8fb32SBenno Lossin         // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
1218fbf8fb32SBenno Lossin         unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), init)? };
1219fbf8fb32SBenno Lossin         // Create the drop guard:
1220fbf8fb32SBenno Lossin         //
1221fbf8fb32SBenno Lossin         // We rely on macro hygiene to make it impossible for users to access this local variable.
1222fbf8fb32SBenno Lossin         // We use `paste!` to create new hygiene for `$field`.
1223dbd5058bSBenno Lossin         $crate::macros::paste! {
1224fbf8fb32SBenno Lossin             // SAFETY: We forget the guard later when initialization has succeeded.
1225fbf8fb32SBenno Lossin             let [< __ $field _guard >] = unsafe {
1226dbd5058bSBenno Lossin                 $crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1227fbf8fb32SBenno Lossin             };
1228fbf8fb32SBenno Lossin 
1229fbf8fb32SBenno Lossin             $crate::__init_internal!(init_slot($use_data):
1230fbf8fb32SBenno Lossin                 @data($data),
1231fbf8fb32SBenno Lossin                 @slot($slot),
1232fbf8fb32SBenno Lossin                 @guards([< __ $field _guard >], $($guards,)*),
1233fbf8fb32SBenno Lossin                 @munch_fields($($rest)*),
1234fbf8fb32SBenno Lossin             );
1235fbf8fb32SBenno Lossin         }
1236fbf8fb32SBenno Lossin     };
1237fbf8fb32SBenno Lossin     (init_slot(): // No `use_data`, so we use `Init::__init` directly.
1238fbf8fb32SBenno Lossin         @data($data:ident),
1239fbf8fb32SBenno Lossin         @slot($slot:ident),
1240fbf8fb32SBenno Lossin         @guards($($guards:ident,)*),
1241fbf8fb32SBenno Lossin         // In-place initialization syntax.
1242fbf8fb32SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1243fbf8fb32SBenno Lossin     ) => {
1244fbf8fb32SBenno Lossin         let init = $val;
1245fbf8fb32SBenno Lossin         // Call the initializer.
1246fbf8fb32SBenno Lossin         //
1247fbf8fb32SBenno Lossin         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1248fbf8fb32SBenno Lossin         // return when an error/panic occurs.
1249dbd5058bSBenno Lossin         unsafe { $crate::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
1250fbf8fb32SBenno Lossin         // Create the drop guard:
1251fbf8fb32SBenno Lossin         //
1252fbf8fb32SBenno Lossin         // We rely on macro hygiene to make it impossible for users to access this local variable.
1253fbf8fb32SBenno Lossin         // We use `paste!` to create new hygiene for `$field`.
1254dbd5058bSBenno Lossin         $crate::macros::paste! {
1255fbf8fb32SBenno Lossin             // SAFETY: We forget the guard later when initialization has succeeded.
1256fbf8fb32SBenno Lossin             let [< __ $field _guard >] = unsafe {
1257dbd5058bSBenno Lossin                 $crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1258fbf8fb32SBenno Lossin             };
1259fbf8fb32SBenno Lossin 
1260fbf8fb32SBenno Lossin             $crate::__init_internal!(init_slot():
1261fbf8fb32SBenno Lossin                 @data($data),
1262fbf8fb32SBenno Lossin                 @slot($slot),
1263fbf8fb32SBenno Lossin                 @guards([< __ $field _guard >], $($guards,)*),
1264fbf8fb32SBenno Lossin                 @munch_fields($($rest)*),
1265fbf8fb32SBenno Lossin             );
1266fbf8fb32SBenno Lossin         }
1267fbf8fb32SBenno Lossin     };
1268fbf8fb32SBenno Lossin     (init_slot($($use_data:ident)?):
1269fbf8fb32SBenno Lossin         @data($data:ident),
1270fbf8fb32SBenno Lossin         @slot($slot:ident),
1271fbf8fb32SBenno Lossin         @guards($($guards:ident,)*),
1272fbf8fb32SBenno Lossin         // Init by-value.
1273fbf8fb32SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1274fbf8fb32SBenno Lossin     ) => {
1275fbf8fb32SBenno Lossin         {
1276fbf8fb32SBenno Lossin             $(let $field = $val;)?
1277fbf8fb32SBenno Lossin             // Initialize the field.
1278fbf8fb32SBenno Lossin             //
1279fbf8fb32SBenno Lossin             // SAFETY: The memory at `slot` is uninitialized.
1280fbf8fb32SBenno Lossin             unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
1281fbf8fb32SBenno Lossin         }
1282fbf8fb32SBenno Lossin         // Create the drop guard:
1283fbf8fb32SBenno Lossin         //
1284fbf8fb32SBenno Lossin         // We rely on macro hygiene to make it impossible for users to access this local variable.
1285fbf8fb32SBenno Lossin         // We use `paste!` to create new hygiene for `$field`.
1286dbd5058bSBenno Lossin         $crate::macros::paste! {
1287fbf8fb32SBenno Lossin             // SAFETY: We forget the guard later when initialization has succeeded.
1288fbf8fb32SBenno Lossin             let [< __ $field _guard >] = unsafe {
1289dbd5058bSBenno Lossin                 $crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1290fbf8fb32SBenno Lossin             };
1291fbf8fb32SBenno Lossin 
1292fbf8fb32SBenno Lossin             $crate::__init_internal!(init_slot($($use_data)?):
1293fbf8fb32SBenno Lossin                 @data($data),
1294fbf8fb32SBenno Lossin                 @slot($slot),
1295fbf8fb32SBenno Lossin                 @guards([< __ $field _guard >], $($guards,)*),
1296fbf8fb32SBenno Lossin                 @munch_fields($($rest)*),
1297fbf8fb32SBenno Lossin             );
1298fbf8fb32SBenno Lossin         }
1299fbf8fb32SBenno Lossin     };
1300fbf8fb32SBenno Lossin     (make_initializer:
1301fbf8fb32SBenno Lossin         @slot($slot:ident),
1302fbf8fb32SBenno Lossin         @type_name($t:path),
1303fbf8fb32SBenno Lossin         @munch_fields(..Zeroable::zeroed() $(,)?),
1304fbf8fb32SBenno Lossin         @acc($($acc:tt)*),
1305fbf8fb32SBenno Lossin     ) => {
1306fbf8fb32SBenno Lossin         // Endpoint, nothing more to munch, create the initializer. Since the users specified
1307fbf8fb32SBenno Lossin         // `..Zeroable::zeroed()`, the slot will already have been zeroed and all field that have
1308fbf8fb32SBenno Lossin         // not been overwritten are thus zero and initialized. We still check that all fields are
1309fbf8fb32SBenno Lossin         // actually accessible by using the struct update syntax ourselves.
1310fbf8fb32SBenno Lossin         // We are inside of a closure that is never executed and thus we can abuse `slot` to
1311fbf8fb32SBenno Lossin         // get the correct type inference here:
1312fbf8fb32SBenno Lossin         #[allow(unused_assignments)]
1313fbf8fb32SBenno Lossin         unsafe {
1314fbf8fb32SBenno Lossin             let mut zeroed = ::core::mem::zeroed();
1315fbf8fb32SBenno Lossin             // We have to use type inference here to make zeroed have the correct type. This does
1316fbf8fb32SBenno Lossin             // not get executed, so it has no effect.
1317fbf8fb32SBenno Lossin             ::core::ptr::write($slot, zeroed);
1318fbf8fb32SBenno Lossin             zeroed = ::core::mem::zeroed();
1319fbf8fb32SBenno Lossin             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1320fbf8fb32SBenno Lossin             // information that is associated to already parsed fragments, so a path fragment
1321fbf8fb32SBenno Lossin             // cannot be used in this position. Doing the retokenization results in valid rust
1322fbf8fb32SBenno Lossin             // code.
1323dbd5058bSBenno Lossin             $crate::macros::paste!(
1324fbf8fb32SBenno Lossin                 ::core::ptr::write($slot, $t {
1325fbf8fb32SBenno Lossin                     $($acc)*
1326fbf8fb32SBenno Lossin                     ..zeroed
1327fbf8fb32SBenno Lossin                 });
1328fbf8fb32SBenno Lossin             );
1329fbf8fb32SBenno Lossin         }
1330fbf8fb32SBenno Lossin     };
1331fbf8fb32SBenno Lossin     (make_initializer:
1332fbf8fb32SBenno Lossin         @slot($slot:ident),
1333fbf8fb32SBenno Lossin         @type_name($t:path),
1334fbf8fb32SBenno Lossin         @munch_fields($(,)?),
1335fbf8fb32SBenno Lossin         @acc($($acc:tt)*),
1336fbf8fb32SBenno Lossin     ) => {
1337fbf8fb32SBenno Lossin         // Endpoint, nothing more to munch, create the initializer.
1338fbf8fb32SBenno Lossin         // Since we are in the closure that is never called, this will never get executed.
1339fbf8fb32SBenno Lossin         // We abuse `slot` to get the correct type inference here:
1340fbf8fb32SBenno Lossin         //
1341fbf8fb32SBenno Lossin         // SAFETY: TODO.
1342fbf8fb32SBenno Lossin         unsafe {
1343fbf8fb32SBenno Lossin             // Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1344fbf8fb32SBenno Lossin             // information that is associated to already parsed fragments, so a path fragment
1345fbf8fb32SBenno Lossin             // cannot be used in this position. Doing the retokenization results in valid rust
1346fbf8fb32SBenno Lossin             // code.
1347dbd5058bSBenno Lossin             $crate::macros::paste!(
1348fbf8fb32SBenno Lossin                 ::core::ptr::write($slot, $t {
1349fbf8fb32SBenno Lossin                     $($acc)*
1350fbf8fb32SBenno Lossin                 });
1351fbf8fb32SBenno Lossin             );
1352fbf8fb32SBenno Lossin         }
1353fbf8fb32SBenno Lossin     };
1354fbf8fb32SBenno Lossin     (make_initializer:
1355fbf8fb32SBenno Lossin         @slot($slot:ident),
1356fbf8fb32SBenno Lossin         @type_name($t:path),
1357fbf8fb32SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1358fbf8fb32SBenno Lossin         @acc($($acc:tt)*),
1359fbf8fb32SBenno Lossin     ) => {
1360fbf8fb32SBenno Lossin         $crate::__init_internal!(make_initializer:
1361fbf8fb32SBenno Lossin             @slot($slot),
1362fbf8fb32SBenno Lossin             @type_name($t),
1363fbf8fb32SBenno Lossin             @munch_fields($($rest)*),
1364fbf8fb32SBenno Lossin             @acc($($acc)* $field: ::core::panic!(),),
1365fbf8fb32SBenno Lossin         );
1366fbf8fb32SBenno Lossin     };
1367fbf8fb32SBenno Lossin     (make_initializer:
1368fbf8fb32SBenno Lossin         @slot($slot:ident),
1369fbf8fb32SBenno Lossin         @type_name($t:path),
1370fbf8fb32SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1371fbf8fb32SBenno Lossin         @acc($($acc:tt)*),
1372fbf8fb32SBenno Lossin     ) => {
1373fbf8fb32SBenno Lossin         $crate::__init_internal!(make_initializer:
1374fbf8fb32SBenno Lossin             @slot($slot),
1375fbf8fb32SBenno Lossin             @type_name($t),
1376fbf8fb32SBenno Lossin             @munch_fields($($rest)*),
1377fbf8fb32SBenno Lossin             @acc($($acc)* $field: ::core::panic!(),),
1378fbf8fb32SBenno Lossin         );
1379fbf8fb32SBenno Lossin     };
1380fbf8fb32SBenno Lossin }
1381fbf8fb32SBenno Lossin 
1382fbf8fb32SBenno Lossin #[doc(hidden)]
1383fbf8fb32SBenno Lossin #[macro_export]
1384fbf8fb32SBenno Lossin macro_rules! __derive_zeroable {
1385fbf8fb32SBenno Lossin     (parse_input:
1386fbf8fb32SBenno Lossin         @sig(
1387fbf8fb32SBenno Lossin             $(#[$($struct_attr:tt)*])*
1388fbf8fb32SBenno Lossin             $vis:vis struct $name:ident
1389fbf8fb32SBenno Lossin             $(where $($whr:tt)*)?
1390fbf8fb32SBenno Lossin         ),
1391fbf8fb32SBenno Lossin         @impl_generics($($impl_generics:tt)*),
1392fbf8fb32SBenno Lossin         @ty_generics($($ty_generics:tt)*),
1393fbf8fb32SBenno Lossin         @body({
1394fbf8fb32SBenno Lossin             $(
1395fbf8fb32SBenno Lossin                 $(#[$($field_attr:tt)*])*
1396983d13fcSBenno Lossin                 $field_vis:vis $field:ident : $field_ty:ty
1397fbf8fb32SBenno Lossin             ),* $(,)?
1398fbf8fb32SBenno Lossin         }),
1399fbf8fb32SBenno Lossin     ) => {
1400fbf8fb32SBenno Lossin         // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
1401fbf8fb32SBenno Lossin         #[automatically_derived]
1402dbd5058bSBenno Lossin         unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
1403fbf8fb32SBenno Lossin         where
1404fbf8fb32SBenno Lossin             $($($whr)*)?
1405fbf8fb32SBenno Lossin         {}
1406fbf8fb32SBenno Lossin         const _: () = {
1407dbd5058bSBenno Lossin             fn assert_zeroable<T: ?::core::marker::Sized + $crate::Zeroable>() {}
1408fbf8fb32SBenno Lossin             fn ensure_zeroable<$($impl_generics)*>()
1409fbf8fb32SBenno Lossin                 where $($($whr)*)?
1410fbf8fb32SBenno Lossin             {
1411fbf8fb32SBenno Lossin                 $(assert_zeroable::<$field_ty>();)*
1412fbf8fb32SBenno Lossin             }
1413fbf8fb32SBenno Lossin         };
1414fbf8fb32SBenno Lossin     };
1415a313d41aSBenno Lossin     (parse_input:
1416a313d41aSBenno Lossin         @sig(
1417a313d41aSBenno Lossin             $(#[$($struct_attr:tt)*])*
1418a313d41aSBenno Lossin             $vis:vis union $name:ident
1419a313d41aSBenno Lossin             $(where $($whr:tt)*)?
1420a313d41aSBenno Lossin         ),
1421a313d41aSBenno Lossin         @impl_generics($($impl_generics:tt)*),
1422a313d41aSBenno Lossin         @ty_generics($($ty_generics:tt)*),
1423a313d41aSBenno Lossin         @body({
1424a313d41aSBenno Lossin             $(
1425a313d41aSBenno Lossin                 $(#[$($field_attr:tt)*])*
1426a313d41aSBenno Lossin                 $field_vis:vis $field:ident : $field_ty:ty
1427a313d41aSBenno Lossin             ),* $(,)?
1428a313d41aSBenno Lossin         }),
1429a313d41aSBenno Lossin     ) => {
1430a313d41aSBenno Lossin         // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
1431a313d41aSBenno Lossin         #[automatically_derived]
1432a313d41aSBenno Lossin         unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
1433a313d41aSBenno Lossin         where
1434a313d41aSBenno Lossin             $($($whr)*)?
1435a313d41aSBenno Lossin         {}
1436a313d41aSBenno Lossin         const _: () = {
1437a313d41aSBenno Lossin             fn assert_zeroable<T: ?::core::marker::Sized + $crate::Zeroable>() {}
1438a313d41aSBenno Lossin             fn ensure_zeroable<$($impl_generics)*>()
1439a313d41aSBenno Lossin                 where $($($whr)*)?
1440a313d41aSBenno Lossin             {
1441a313d41aSBenno Lossin                 $(assert_zeroable::<$field_ty>();)*
1442a313d41aSBenno Lossin             }
1443a313d41aSBenno Lossin         };
1444a313d41aSBenno Lossin     };
1445fbf8fb32SBenno Lossin }
1446*00fccd3eSBenno Lossin 
1447*00fccd3eSBenno Lossin #[doc(hidden)]
1448*00fccd3eSBenno Lossin #[macro_export]
1449*00fccd3eSBenno Lossin macro_rules! __maybe_derive_zeroable {
1450*00fccd3eSBenno Lossin     (parse_input:
1451*00fccd3eSBenno Lossin         @sig(
1452*00fccd3eSBenno Lossin             $(#[$($struct_attr:tt)*])*
1453*00fccd3eSBenno Lossin             $vis:vis struct $name:ident
1454*00fccd3eSBenno Lossin             $(where $($whr:tt)*)?
1455*00fccd3eSBenno Lossin         ),
1456*00fccd3eSBenno Lossin         @impl_generics($($impl_generics:tt)*),
1457*00fccd3eSBenno Lossin         @ty_generics($($ty_generics:tt)*),
1458*00fccd3eSBenno Lossin         @body({
1459*00fccd3eSBenno Lossin             $(
1460*00fccd3eSBenno Lossin                 $(#[$($field_attr:tt)*])*
1461*00fccd3eSBenno Lossin                 $field_vis:vis $field:ident : $field_ty:ty
1462*00fccd3eSBenno Lossin             ),* $(,)?
1463*00fccd3eSBenno Lossin         }),
1464*00fccd3eSBenno Lossin     ) => {
1465*00fccd3eSBenno Lossin         // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
1466*00fccd3eSBenno Lossin         #[automatically_derived]
1467*00fccd3eSBenno Lossin         unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
1468*00fccd3eSBenno Lossin         where
1469*00fccd3eSBenno Lossin             $(
1470*00fccd3eSBenno Lossin                 // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
1471*00fccd3eSBenno Lossin                 // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
1472*00fccd3eSBenno Lossin                 $field_ty: for<'__dummy> $crate::Zeroable,
1473*00fccd3eSBenno Lossin             )*
1474*00fccd3eSBenno Lossin             $($($whr)*)?
1475*00fccd3eSBenno Lossin         {}
1476*00fccd3eSBenno Lossin     };
1477*00fccd3eSBenno Lossin     (parse_input:
1478*00fccd3eSBenno Lossin         @sig(
1479*00fccd3eSBenno Lossin             $(#[$($struct_attr:tt)*])*
1480*00fccd3eSBenno Lossin             $vis:vis union $name:ident
1481*00fccd3eSBenno Lossin             $(where $($whr:tt)*)?
1482*00fccd3eSBenno Lossin         ),
1483*00fccd3eSBenno Lossin         @impl_generics($($impl_generics:tt)*),
1484*00fccd3eSBenno Lossin         @ty_generics($($ty_generics:tt)*),
1485*00fccd3eSBenno Lossin         @body({
1486*00fccd3eSBenno Lossin             $(
1487*00fccd3eSBenno Lossin                 $(#[$($field_attr:tt)*])*
1488*00fccd3eSBenno Lossin                 $field_vis:vis $field:ident : $field_ty:ty
1489*00fccd3eSBenno Lossin             ),* $(,)?
1490*00fccd3eSBenno Lossin         }),
1491*00fccd3eSBenno Lossin     ) => {
1492*00fccd3eSBenno Lossin         // SAFETY: Every field type implements `Zeroable` and padding bytes may be zero.
1493*00fccd3eSBenno Lossin         #[automatically_derived]
1494*00fccd3eSBenno Lossin         unsafe impl<$($impl_generics)*> $crate::Zeroable for $name<$($ty_generics)*>
1495*00fccd3eSBenno Lossin         where
1496*00fccd3eSBenno Lossin             $(
1497*00fccd3eSBenno Lossin                 // the `for<'__dummy>` HRTB makes this not error without the `trivial_bounds`
1498*00fccd3eSBenno Lossin                 // feature <https://github.com/rust-lang/rust/issues/48214#issuecomment-2557829956>.
1499*00fccd3eSBenno Lossin                 $field_ty: for<'__dummy> $crate::Zeroable,
1500*00fccd3eSBenno Lossin             )*
1501*00fccd3eSBenno Lossin             $($($whr)*)?
1502*00fccd3eSBenno Lossin         {}
1503*00fccd3eSBenno Lossin     };
1504*00fccd3eSBenno Lossin }
1505