xref: /openbmc/linux/rust/kernel/init/macros.rs (revision f8badd150763ae0f9c8482fabe0fdbac81735d34)
1fc6c6baaSBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
2fc6c6baaSBenno Lossin 
3fc6c6baaSBenno Lossin //! This module provides the macros that actually implement the proc-macros `pin_data` and
4b3068ac3SBenno Lossin //! `pinned_drop`. It also contains `__init_internal` the implementation of the `{try_}{pin_}init!`
5b3068ac3SBenno Lossin //! macros.
6fc6c6baaSBenno Lossin //!
7fc6c6baaSBenno Lossin //! These macros should never be called directly, since they expect their input to be
8b3068ac3SBenno Lossin //! in a certain format which is internal. If used incorrectly, these macros can lead to UB even in
9b3068ac3SBenno Lossin //! safe code! Use the public facing macros instead.
10fc6c6baaSBenno Lossin //!
11fc6c6baaSBenno Lossin //! This architecture has been chosen because the kernel does not yet have access to `syn` which
12fc6c6baaSBenno Lossin //! would make matters a lot easier for implementing these as proc-macros.
13fc6c6baaSBenno Lossin //!
14fc6c6baaSBenno Lossin //! # Macro expansion example
15fc6c6baaSBenno Lossin //!
16fc6c6baaSBenno Lossin //! This section is intended for readers trying to understand the macros in this module and the
17fc6c6baaSBenno Lossin //! `pin_init!` macros from `init.rs`.
18fc6c6baaSBenno Lossin //!
19fc6c6baaSBenno Lossin //! We will look at the following example:
20fc6c6baaSBenno Lossin //!
21309786c2SBenno Lossin //! ```rust,ignore
22fc6c6baaSBenno Lossin //! # use kernel::init::*;
23309786c2SBenno Lossin //! # use core::pin::Pin;
24fc6c6baaSBenno Lossin //! #[pin_data]
25fc6c6baaSBenno Lossin //! #[repr(C)]
26fc6c6baaSBenno Lossin //! struct Bar<T> {
27fc6c6baaSBenno Lossin //!     #[pin]
28fc6c6baaSBenno Lossin //!     t: T,
29fc6c6baaSBenno Lossin //!     pub x: usize,
30fc6c6baaSBenno Lossin //! }
31fc6c6baaSBenno Lossin //!
32fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
33fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
34fc6c6baaSBenno Lossin //!         pin_init!(Self { t, x: 0 })
35fc6c6baaSBenno Lossin //!     }
36fc6c6baaSBenno Lossin //! }
37d0fdc396SBenno Lossin //!
38d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)]
39d0fdc396SBenno Lossin //! struct Foo {
40d0fdc396SBenno Lossin //!     a: usize,
41d0fdc396SBenno Lossin //!     #[pin]
42d0fdc396SBenno Lossin //!     b: Bar<u32>,
43d0fdc396SBenno Lossin //! }
44d0fdc396SBenno Lossin //!
45d0fdc396SBenno Lossin //! #[pinned_drop]
46d0fdc396SBenno Lossin //! impl PinnedDrop for Foo {
47d0fdc396SBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
48d0fdc396SBenno Lossin //!         println!("{self:p} is getting dropped.");
49d0fdc396SBenno Lossin //!     }
50d0fdc396SBenno Lossin //! }
51d0fdc396SBenno Lossin //!
52d0fdc396SBenno Lossin //! let a = 42;
53d0fdc396SBenno Lossin //! let initializer = pin_init!(Foo {
54d0fdc396SBenno Lossin //!     a,
55d0fdc396SBenno Lossin //!     b <- Bar::new(36),
56d0fdc396SBenno Lossin //! });
57fc6c6baaSBenno Lossin //! ```
58fc6c6baaSBenno Lossin //!
59fc6c6baaSBenno Lossin //! This example includes the most common and important features of the pin-init API.
60fc6c6baaSBenno Lossin //!
61fc6c6baaSBenno Lossin //! Below you can find individual section about the different macro invocations. Here are some
62fc6c6baaSBenno Lossin //! general things we need to take into account when designing macros:
63fc6c6baaSBenno Lossin //! - use global paths, similarly to file paths, these start with the separator: `::core::panic!()`
64fc6c6baaSBenno Lossin //!   this ensures that the correct item is used, since users could define their own `mod core {}`
65fc6c6baaSBenno Lossin //!   and then their own `panic!` inside to execute arbitrary code inside of our macro.
66fc6c6baaSBenno Lossin //! - macro `unsafe` hygiene: we need to ensure that we do not expand arbitrary, user-supplied
67fc6c6baaSBenno Lossin //!   expressions inside of an `unsafe` block in the macro, because this would allow users to do
68fc6c6baaSBenno Lossin //!   `unsafe` operations without an associated `unsafe` block.
69fc6c6baaSBenno Lossin //!
70fc6c6baaSBenno Lossin //! ## `#[pin_data]` on `Bar`
71fc6c6baaSBenno Lossin //!
72fc6c6baaSBenno Lossin //! This macro is used to specify which fields are structurally pinned and which fields are not. It
73fc6c6baaSBenno Lossin //! is placed on the struct definition and allows `#[pin]` to be placed on the fields.
74fc6c6baaSBenno Lossin //!
75fc6c6baaSBenno Lossin //! Here is the definition of `Bar` from our example:
76fc6c6baaSBenno Lossin //!
77309786c2SBenno Lossin //! ```rust,ignore
78fc6c6baaSBenno Lossin //! # use kernel::init::*;
79fc6c6baaSBenno Lossin //! #[pin_data]
80fc6c6baaSBenno Lossin //! #[repr(C)]
81fc6c6baaSBenno Lossin //! struct Bar<T> {
82309786c2SBenno Lossin //!     #[pin]
83fc6c6baaSBenno Lossin //!     t: T,
84fc6c6baaSBenno Lossin //!     pub x: usize,
85fc6c6baaSBenno Lossin //! }
86fc6c6baaSBenno Lossin //! ```
87fc6c6baaSBenno Lossin //!
88fc6c6baaSBenno Lossin //! This expands to the following code:
89fc6c6baaSBenno Lossin //!
90309786c2SBenno Lossin //! ```rust,ignore
91fc6c6baaSBenno Lossin //! // Firstly the normal definition of the struct, attributes are preserved:
92fc6c6baaSBenno Lossin //! #[repr(C)]
93fc6c6baaSBenno Lossin //! struct Bar<T> {
94fc6c6baaSBenno Lossin //!     t: T,
95fc6c6baaSBenno Lossin //!     pub x: usize,
96fc6c6baaSBenno Lossin //! }
97fc6c6baaSBenno Lossin //! // Then an anonymous constant is defined, this is because we do not want any code to access the
98fc6c6baaSBenno Lossin //! // types that we define inside:
99fc6c6baaSBenno Lossin //! const _: () = {
100fc6c6baaSBenno Lossin //!     // We define the pin-data carrying struct, it is a ZST and needs to have the same generics,
101fc6c6baaSBenno Lossin //!     // since we need to implement access functions for each field and thus need to know its
102fc6c6baaSBenno Lossin //!     // type.
103fc6c6baaSBenno Lossin //!     struct __ThePinData<T> {
104fc6c6baaSBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
105fc6c6baaSBenno Lossin //!     }
106fc6c6baaSBenno Lossin //!     // We implement `Copy` for the pin-data struct, since all functions it defines will take
107fc6c6baaSBenno Lossin //!     // `self` by value.
108fc6c6baaSBenno Lossin //!     impl<T> ::core::clone::Clone for __ThePinData<T> {
109fc6c6baaSBenno Lossin //!         fn clone(&self) -> Self {
110fc6c6baaSBenno Lossin //!             *self
111fc6c6baaSBenno Lossin //!         }
112fc6c6baaSBenno Lossin //!     }
113fc6c6baaSBenno Lossin //!     impl<T> ::core::marker::Copy for __ThePinData<T> {}
114fc6c6baaSBenno Lossin //!     // For every field of `Bar`, the pin-data struct will define a function with the same name
115fc6c6baaSBenno Lossin //!     // and accessor (`pub` or `pub(crate)` etc.). This function will take a pointer to the
116fc6c6baaSBenno Lossin //!     // field (`slot`) and a `PinInit` or `Init` depending on the projection kind of the field
117fc6c6baaSBenno Lossin //!     // (if pinning is structural for the field, then `PinInit` otherwise `Init`).
118fc6c6baaSBenno Lossin //!     #[allow(dead_code)]
119fc6c6baaSBenno Lossin //!     impl<T> __ThePinData<T> {
120fc6c6baaSBenno Lossin //!         unsafe fn t<E>(
121fc6c6baaSBenno Lossin //!             self,
122fc6c6baaSBenno Lossin //!             slot: *mut T,
123309786c2SBenno Lossin //!             // Since `t` is `#[pin]`, this is `PinInit`.
124309786c2SBenno Lossin //!             init: impl ::kernel::init::PinInit<T, E>,
125fc6c6baaSBenno Lossin //!         ) -> ::core::result::Result<(), E> {
126309786c2SBenno Lossin //!             unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
127fc6c6baaSBenno Lossin //!         }
128fc6c6baaSBenno Lossin //!         pub unsafe fn x<E>(
129fc6c6baaSBenno Lossin //!             self,
130fc6c6baaSBenno Lossin //!             slot: *mut usize,
131309786c2SBenno Lossin //!             // Since `x` is not `#[pin]`, this is `Init`.
132fc6c6baaSBenno Lossin //!             init: impl ::kernel::init::Init<usize, E>,
133fc6c6baaSBenno Lossin //!         ) -> ::core::result::Result<(), E> {
134fc6c6baaSBenno Lossin //!             unsafe { ::kernel::init::Init::__init(init, slot) }
135fc6c6baaSBenno Lossin //!         }
136fc6c6baaSBenno Lossin //!     }
137fc6c6baaSBenno Lossin //!     // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct
138309786c2SBenno Lossin //!     // that we constructed above.
139fc6c6baaSBenno Lossin //!     unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> {
140fc6c6baaSBenno Lossin //!         type PinData = __ThePinData<T>;
141fc6c6baaSBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
142fc6c6baaSBenno Lossin //!             __ThePinData {
143fc6c6baaSBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
144fc6c6baaSBenno Lossin //!             }
145fc6c6baaSBenno Lossin //!         }
146fc6c6baaSBenno Lossin //!     }
147fc6c6baaSBenno Lossin //!     // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data
148fc6c6baaSBenno Lossin //!     // struct. This is important to ensure that no user can implement a rouge `__pin_data`
149fc6c6baaSBenno Lossin //!     // function without using `unsafe`.
150fc6c6baaSBenno Lossin //!     unsafe impl<T> ::kernel::init::__internal::PinData for __ThePinData<T> {
151fc6c6baaSBenno Lossin //!         type Datee = Bar<T>;
152fc6c6baaSBenno Lossin //!     }
153fc6c6baaSBenno Lossin //!     // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is
154fc6c6baaSBenno Lossin //!     // `Unpin`. In other words, whether `Bar` is `Unpin` only depends on structurally pinned
155fc6c6baaSBenno Lossin //!     // fields (those marked with `#[pin]`). These fields will be listed in this struct, in our
156fc6c6baaSBenno Lossin //!     // case no such fields exist, hence this is almost empty. The two phantomdata fields exist
157fc6c6baaSBenno Lossin //!     // for two reasons:
158fc6c6baaSBenno Lossin //!     // - `__phantom`: every generic must be used, since we cannot really know which generics
159fc6c6baaSBenno Lossin //!     //   are used, we declere all and then use everything here once.
160fc6c6baaSBenno Lossin //!     // - `__phantom_pin`: uses the `'__pin` lifetime and ensures that this struct is invariant
161fc6c6baaSBenno Lossin //!     //   over it. The lifetime is needed to work around the limitation that trait bounds must
162fc6c6baaSBenno Lossin //!     //   not be trivial, e.g. the user has a `#[pin] PhantomPinned` field -- this is
163fc6c6baaSBenno Lossin //!     //   unconditionally `!Unpin` and results in an error. The lifetime tricks the compiler
164fc6c6baaSBenno Lossin //!     //   into accepting these bounds regardless.
165fc6c6baaSBenno Lossin //!     #[allow(dead_code)]
166fc6c6baaSBenno Lossin //!     struct __Unpin<'__pin, T> {
167fc6c6baaSBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
168fc6c6baaSBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>,
169309786c2SBenno Lossin //!         // Our only `#[pin]` field is `t`.
170309786c2SBenno Lossin //!         t: T,
171fc6c6baaSBenno Lossin //!     }
172fc6c6baaSBenno Lossin //!     #[doc(hidden)]
173fc6c6baaSBenno Lossin //!     impl<'__pin, T>
174fc6c6baaSBenno Lossin //!         ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {}
175fc6c6baaSBenno Lossin //!     // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users
176fc6c6baaSBenno Lossin //!     // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to
177fc6c6baaSBenno Lossin //!     // UB with only safe code, so we disallow this by giving a trait implementation error using
178fc6c6baaSBenno Lossin //!     // a direct impl and a blanket implementation.
179fc6c6baaSBenno Lossin //!     trait MustNotImplDrop {}
180fc6c6baaSBenno Lossin //!     // Normally `Drop` bounds do not have the correct semantics, but for this purpose they do
181fc6c6baaSBenno Lossin //!     // (normally people want to know if a type has any kind of drop glue at all, here we want
182fc6c6baaSBenno Lossin //!     // to know if it has any kind of custom drop glue, which is exactly what this bound does).
183fc6c6baaSBenno Lossin //!     #[allow(drop_bounds)]
184fc6c6baaSBenno Lossin //!     impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
185fc6c6baaSBenno Lossin //!     impl<T> MustNotImplDrop for Bar<T> {}
186d0fdc396SBenno Lossin //!     // Here comes a convenience check, if one implemented `PinnedDrop`, but forgot to add it to
187d0fdc396SBenno Lossin //!     // `#[pin_data]`, then this will error with the same mechanic as above, this is not needed
188d0fdc396SBenno Lossin //!     // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`.
189d0fdc396SBenno Lossin //!     #[allow(non_camel_case_types)]
190d0fdc396SBenno Lossin //!     trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
191d0fdc396SBenno Lossin //!     impl<T: ::kernel::init::PinnedDrop>
192d0fdc396SBenno Lossin //!         UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
193d0fdc396SBenno Lossin //!     impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {}
194fc6c6baaSBenno Lossin //! };
195fc6c6baaSBenno Lossin //! ```
196fc6c6baaSBenno Lossin //!
197fc6c6baaSBenno Lossin //! ## `pin_init!` in `impl Bar`
198fc6c6baaSBenno Lossin //!
199fc6c6baaSBenno Lossin //! This macro creates an pin-initializer for the given struct. It requires that the struct is
200fc6c6baaSBenno Lossin //! annotated by `#[pin_data]`.
201fc6c6baaSBenno Lossin //!
202fc6c6baaSBenno Lossin //! Here is the impl on `Bar` defining the new function:
203fc6c6baaSBenno Lossin //!
204309786c2SBenno Lossin //! ```rust,ignore
205fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
206fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
207fc6c6baaSBenno Lossin //!         pin_init!(Self { t, x: 0 })
208fc6c6baaSBenno Lossin //!     }
209fc6c6baaSBenno Lossin //! }
210fc6c6baaSBenno Lossin //! ```
211fc6c6baaSBenno Lossin //!
212fc6c6baaSBenno Lossin //! This expands to the following code:
213fc6c6baaSBenno Lossin //!
214309786c2SBenno Lossin //! ```rust,ignore
215fc6c6baaSBenno Lossin //! impl<T> Bar<T> {
216fc6c6baaSBenno Lossin //!     fn new(t: T) -> impl PinInit<Self> {
217fc6c6baaSBenno Lossin //!         {
218fc6c6baaSBenno Lossin //!             // We do not want to allow arbitrary returns, so we declare this type as the `Ok`
219fc6c6baaSBenno Lossin //!             // return type and shadow it later when we insert the arbitrary user code. That way
220fc6c6baaSBenno Lossin //!             // there will be no possibility of returning without `unsafe`.
221fc6c6baaSBenno Lossin //!             struct __InitOk;
222fc6c6baaSBenno Lossin //!             // Get the pin-data type from the initialized type.
223fc6c6baaSBenno Lossin //!             // - the function is unsafe, hence the unsafe block
224fc6c6baaSBenno Lossin //!             // - we `use` the `HasPinData` trait in the block, it is only available in that
225fc6c6baaSBenno Lossin //!             //   scope.
226fc6c6baaSBenno Lossin //!             let data = unsafe {
227fc6c6baaSBenno Lossin //!                 use ::kernel::init::__internal::HasPinData;
228fc6c6baaSBenno Lossin //!                 Self::__pin_data()
229fc6c6baaSBenno Lossin //!             };
230fc6c6baaSBenno Lossin //!             // Use `data` to help with type inference, the closure supplied will have the type
231fc6c6baaSBenno Lossin //!             // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`.
232fc6c6baaSBenno Lossin //!             let init = ::kernel::init::__internal::PinData::make_closure::<
233fc6c6baaSBenno Lossin //!                 _,
234fc6c6baaSBenno Lossin //!                 __InitOk,
235fc6c6baaSBenno Lossin //!                 ::core::convert::Infallible,
236fc6c6baaSBenno Lossin //!             >(data, move |slot| {
237fc6c6baaSBenno Lossin //!                 {
238fc6c6baaSBenno Lossin //!                     // Shadow the structure so it cannot be used to return early. If a user
239fc6c6baaSBenno Lossin //!                     // tries to write `return Ok(__InitOk)`, then they get a type error, since
240fc6c6baaSBenno Lossin //!                     // that will refer to this struct instead of the one defined above.
241fc6c6baaSBenno Lossin //!                     struct __InitOk;
242fc6c6baaSBenno Lossin //!                     // This is the expansion of `t,`, which is syntactic sugar for `t: t,`.
243309786c2SBenno Lossin //!                     unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) };
244fc6c6baaSBenno Lossin //!                     // Since initialization could fail later (not in this case, since the error
245309786c2SBenno Lossin //!                     // type is `Infallible`) we will need to drop this field if there is an
246309786c2SBenno Lossin //!                     // error later. This `DropGuard` will drop the field when it gets dropped
247309786c2SBenno Lossin //!                     // and has not yet been forgotten. We make a reference to it, so users
248309786c2SBenno Lossin //!                     // cannot `mem::forget` it from the initializer, since the name is the same
249309786c2SBenno Lossin //!                     // as the field (including hygiene).
250fc6c6baaSBenno Lossin //!                     let t = &unsafe {
251309786c2SBenno Lossin //!                         ::kernel::init::__internal::DropGuard::new(
252309786c2SBenno Lossin //!                             ::core::addr_of_mut!((*slot).t),
253309786c2SBenno Lossin //!                         )
254fc6c6baaSBenno Lossin //!                     };
255fc6c6baaSBenno Lossin //!                     // Expansion of `x: 0,`:
256fc6c6baaSBenno Lossin //!                     // Since this can be an arbitrary expression we cannot place it inside of
257fc6c6baaSBenno Lossin //!                     // the `unsafe` block, so we bind it here.
258fc6c6baaSBenno Lossin //!                     let x = 0;
259309786c2SBenno Lossin //!                     unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) };
260309786c2SBenno Lossin //!                     // We again create a `DropGuard`.
261fc6c6baaSBenno Lossin //!                     let x = &unsafe {
262309786c2SBenno Lossin //!                         ::kernel::init::__internal::DropGuard::new(
263309786c2SBenno Lossin //!                             ::core::addr_of_mut!((*slot).x),
264309786c2SBenno Lossin //!                         )
265fc6c6baaSBenno Lossin //!                     };
266fc6c6baaSBenno Lossin //!
267309786c2SBenno Lossin //!                     // Here we use the type checker to ensure that every field has been
268fc6c6baaSBenno Lossin //!                     // initialized exactly once, since this is `if false` it will never get
269fc6c6baaSBenno Lossin //!                     // executed, but still type-checked.
270fc6c6baaSBenno Lossin //!                     // Additionally we abuse `slot` to automatically infer the correct type for
271fc6c6baaSBenno Lossin //!                     // the struct. This is also another check that every field is accessible
272fc6c6baaSBenno Lossin //!                     // from this scope.
273fc6c6baaSBenno Lossin //!                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
274fc6c6baaSBenno Lossin //!                     if false {
275fc6c6baaSBenno Lossin //!                         unsafe {
276fc6c6baaSBenno Lossin //!                             ::core::ptr::write(
277fc6c6baaSBenno Lossin //!                                 slot,
278fc6c6baaSBenno Lossin //!                                 Self {
279fc6c6baaSBenno Lossin //!                                     // We only care about typecheck finding every field here,
280fc6c6baaSBenno Lossin //!                                     // the expression does not matter, just conjure one using
281fc6c6baaSBenno Lossin //!                                     // `panic!()`:
282fc6c6baaSBenno Lossin //!                                     t: ::core::panic!(),
283fc6c6baaSBenno Lossin //!                                     x: ::core::panic!(),
284fc6c6baaSBenno Lossin //!                                 },
285fc6c6baaSBenno Lossin //!                             );
286fc6c6baaSBenno Lossin //!                         };
287fc6c6baaSBenno Lossin //!                     }
288fc6c6baaSBenno Lossin //!                     // Since initialization has successfully completed, we can now forget the
289309786c2SBenno Lossin //!                     // guards. This is not `mem::forget`, since we only have `&DropGuard`.
290fc6c6baaSBenno Lossin //!                     unsafe { ::kernel::init::__internal::DropGuard::forget(t) };
291fc6c6baaSBenno Lossin //!                     unsafe { ::kernel::init::__internal::DropGuard::forget(x) };
292fc6c6baaSBenno Lossin //!                 }
293fc6c6baaSBenno Lossin //!                 // We leave the scope above and gain access to the previously shadowed
294fc6c6baaSBenno Lossin //!                 // `__InitOk` that we need to return.
295fc6c6baaSBenno Lossin //!                 Ok(__InitOk)
296fc6c6baaSBenno Lossin //!             });
297309786c2SBenno Lossin //!             // Change the return type from `__InitOk` to `()`.
298fc6c6baaSBenno Lossin //!             let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> {
299fc6c6baaSBenno Lossin //!                 init(slot).map(|__InitOk| ())
300fc6c6baaSBenno Lossin //!             };
301fc6c6baaSBenno Lossin //!             // Construct the initializer.
302fc6c6baaSBenno Lossin //!             let init = unsafe {
303fc6c6baaSBenno Lossin //!                 ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
304fc6c6baaSBenno Lossin //!             };
305fc6c6baaSBenno Lossin //!             init
306fc6c6baaSBenno Lossin //!         }
307fc6c6baaSBenno Lossin //!     }
308fc6c6baaSBenno Lossin //! }
309fc6c6baaSBenno Lossin //! ```
310d0fdc396SBenno Lossin //!
311d0fdc396SBenno Lossin //! ## `#[pin_data]` on `Foo`
312d0fdc396SBenno Lossin //!
313d0fdc396SBenno Lossin //! Since we already took a look at `#[pin_data]` on `Bar`, this section will only explain the
314d0fdc396SBenno Lossin //! differences/new things in the expansion of the `Foo` definition:
315d0fdc396SBenno Lossin //!
316309786c2SBenno Lossin //! ```rust,ignore
317d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)]
318d0fdc396SBenno Lossin //! struct Foo {
319d0fdc396SBenno Lossin //!     a: usize,
320d0fdc396SBenno Lossin //!     #[pin]
321d0fdc396SBenno Lossin //!     b: Bar<u32>,
322d0fdc396SBenno Lossin //! }
323d0fdc396SBenno Lossin //! ```
324d0fdc396SBenno Lossin //!
325d0fdc396SBenno Lossin //! This expands to the following code:
326d0fdc396SBenno Lossin //!
327309786c2SBenno Lossin //! ```rust,ignore
328d0fdc396SBenno Lossin //! struct Foo {
329d0fdc396SBenno Lossin //!     a: usize,
330d0fdc396SBenno Lossin //!     b: Bar<u32>,
331d0fdc396SBenno Lossin //! }
332d0fdc396SBenno Lossin //! const _: () = {
333d0fdc396SBenno Lossin //!     struct __ThePinData {
334d0fdc396SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
335d0fdc396SBenno Lossin //!     }
336d0fdc396SBenno Lossin //!     impl ::core::clone::Clone for __ThePinData {
337d0fdc396SBenno Lossin //!         fn clone(&self) -> Self {
338d0fdc396SBenno Lossin //!             *self
339d0fdc396SBenno Lossin //!         }
340d0fdc396SBenno Lossin //!     }
341d0fdc396SBenno Lossin //!     impl ::core::marker::Copy for __ThePinData {}
342d0fdc396SBenno Lossin //!     #[allow(dead_code)]
343d0fdc396SBenno Lossin //!     impl __ThePinData {
344d0fdc396SBenno Lossin //!         unsafe fn b<E>(
345d0fdc396SBenno Lossin //!             self,
346d0fdc396SBenno Lossin //!             slot: *mut Bar<u32>,
347d0fdc396SBenno Lossin //!             init: impl ::kernel::init::PinInit<Bar<u32>, E>,
348d0fdc396SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
349d0fdc396SBenno Lossin //!             unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) }
350d0fdc396SBenno Lossin //!         }
351d0fdc396SBenno Lossin //!         unsafe fn a<E>(
352d0fdc396SBenno Lossin //!             self,
353d0fdc396SBenno Lossin //!             slot: *mut usize,
354d0fdc396SBenno Lossin //!             init: impl ::kernel::init::Init<usize, E>,
355d0fdc396SBenno Lossin //!         ) -> ::core::result::Result<(), E> {
356d0fdc396SBenno Lossin //!             unsafe { ::kernel::init::Init::__init(init, slot) }
357d0fdc396SBenno Lossin //!         }
358d0fdc396SBenno Lossin //!     }
359d0fdc396SBenno Lossin //!     unsafe impl ::kernel::init::__internal::HasPinData for Foo {
360d0fdc396SBenno Lossin //!         type PinData = __ThePinData;
361d0fdc396SBenno Lossin //!         unsafe fn __pin_data() -> Self::PinData {
362d0fdc396SBenno Lossin //!             __ThePinData {
363d0fdc396SBenno Lossin //!                 __phantom: ::core::marker::PhantomData,
364d0fdc396SBenno Lossin //!             }
365d0fdc396SBenno Lossin //!         }
366d0fdc396SBenno Lossin //!     }
367d0fdc396SBenno Lossin //!     unsafe impl ::kernel::init::__internal::PinData for __ThePinData {
368d0fdc396SBenno Lossin //!         type Datee = Foo;
369d0fdc396SBenno Lossin //!     }
370d0fdc396SBenno Lossin //!     #[allow(dead_code)]
371d0fdc396SBenno Lossin //!     struct __Unpin<'__pin> {
372d0fdc396SBenno Lossin //!         __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
373d0fdc396SBenno Lossin //!         __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>,
374d0fdc396SBenno Lossin //!         b: Bar<u32>,
375d0fdc396SBenno Lossin //!     }
376d0fdc396SBenno Lossin //!     #[doc(hidden)]
377d0fdc396SBenno Lossin //!     impl<'__pin> ::core::marker::Unpin for Foo where __Unpin<'__pin>: ::core::marker::Unpin {}
378d0fdc396SBenno Lossin //!     // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to
379d0fdc396SBenno Lossin //!     // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like
380309786c2SBenno Lossin //!     // before, instead we implement `Drop` here and delegate to `PinnedDrop`.
381d0fdc396SBenno Lossin //!     impl ::core::ops::Drop for Foo {
382d0fdc396SBenno Lossin //!         fn drop(&mut self) {
383d0fdc396SBenno Lossin //!             // Since we are getting dropped, no one else has a reference to `self` and thus we
384d0fdc396SBenno Lossin //!             // can assume that we never move.
385d0fdc396SBenno Lossin //!             let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
386d0fdc396SBenno Lossin //!             // Create the unsafe token that proves that we are inside of a destructor, this
387d0fdc396SBenno Lossin //!             // type is only allowed to be created in a destructor.
388d0fdc396SBenno Lossin //!             let token = unsafe { ::kernel::init::__internal::OnlyCallFromDrop::new() };
389d0fdc396SBenno Lossin //!             ::kernel::init::PinnedDrop::drop(pinned, token);
390d0fdc396SBenno Lossin //!         }
391d0fdc396SBenno Lossin //!     }
392d0fdc396SBenno Lossin //! };
393d0fdc396SBenno Lossin //! ```
394d0fdc396SBenno Lossin //!
395d0fdc396SBenno Lossin //! ## `#[pinned_drop]` on `impl PinnedDrop for Foo`
396d0fdc396SBenno Lossin //!
397d0fdc396SBenno Lossin //! This macro is used to implement the `PinnedDrop` trait, since that trait is `unsafe` and has an
398d0fdc396SBenno Lossin //! extra parameter that should not be used at all. The macro hides that parameter.
399d0fdc396SBenno Lossin //!
400d0fdc396SBenno Lossin //! Here is the `PinnedDrop` impl for `Foo`:
401d0fdc396SBenno Lossin //!
402309786c2SBenno Lossin //! ```rust,ignore
403d0fdc396SBenno Lossin //! #[pinned_drop]
404d0fdc396SBenno Lossin //! impl PinnedDrop for Foo {
405d0fdc396SBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
406d0fdc396SBenno Lossin //!         println!("{self:p} is getting dropped.");
407d0fdc396SBenno Lossin //!     }
408d0fdc396SBenno Lossin //! }
409d0fdc396SBenno Lossin //! ```
410d0fdc396SBenno Lossin //!
411d0fdc396SBenno Lossin //! This expands to the following code:
412d0fdc396SBenno Lossin //!
413309786c2SBenno Lossin //! ```rust,ignore
414d0fdc396SBenno Lossin //! // `unsafe`, full path and the token parameter are added, everything else stays the same.
415d0fdc396SBenno Lossin //! unsafe impl ::kernel::init::PinnedDrop for Foo {
416d0fdc396SBenno Lossin //!     fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) {
417d0fdc396SBenno Lossin //!         println!("{self:p} is getting dropped.");
418d0fdc396SBenno Lossin //!     }
419d0fdc396SBenno Lossin //! }
420d0fdc396SBenno Lossin //! ```
421d0fdc396SBenno Lossin //!
422d0fdc396SBenno Lossin //! ## `pin_init!` on `Foo`
423d0fdc396SBenno Lossin //!
424309786c2SBenno Lossin //! Since we already took a look at `pin_init!` on `Bar`, this section will only show the expansion
425309786c2SBenno Lossin //! of `pin_init!` on `Foo`:
426d0fdc396SBenno Lossin //!
427309786c2SBenno Lossin //! ```rust,ignore
428d0fdc396SBenno Lossin //! let a = 42;
429d0fdc396SBenno Lossin //! let initializer = pin_init!(Foo {
430d0fdc396SBenno Lossin //!     a,
431d0fdc396SBenno Lossin //!     b <- Bar::new(36),
432d0fdc396SBenno Lossin //! });
433d0fdc396SBenno Lossin //! ```
434d0fdc396SBenno Lossin //!
435d0fdc396SBenno Lossin //! This expands to the following code:
436d0fdc396SBenno Lossin //!
437309786c2SBenno Lossin //! ```rust,ignore
438d0fdc396SBenno Lossin //! let a = 42;
439d0fdc396SBenno Lossin //! let initializer = {
440d0fdc396SBenno Lossin //!     struct __InitOk;
441d0fdc396SBenno Lossin //!     let data = unsafe {
442d0fdc396SBenno Lossin //!         use ::kernel::init::__internal::HasPinData;
443d0fdc396SBenno Lossin //!         Foo::__pin_data()
444d0fdc396SBenno Lossin //!     };
445d0fdc396SBenno Lossin //!     let init = ::kernel::init::__internal::PinData::make_closure::<
446d0fdc396SBenno Lossin //!         _,
447d0fdc396SBenno Lossin //!         __InitOk,
448d0fdc396SBenno Lossin //!         ::core::convert::Infallible,
449d0fdc396SBenno Lossin //!     >(data, move |slot| {
450d0fdc396SBenno Lossin //!         {
451d0fdc396SBenno Lossin //!             struct __InitOk;
452309786c2SBenno Lossin //!             unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) };
453309786c2SBenno Lossin //!             let a = &unsafe {
454309786c2SBenno Lossin //!                 ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a))
455309786c2SBenno Lossin //!             };
456d0fdc396SBenno Lossin //!             let b = Bar::new(36);
457309786c2SBenno Lossin //!             unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? };
458309786c2SBenno Lossin //!             let b = &unsafe {
459309786c2SBenno Lossin //!                 ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b))
460309786c2SBenno Lossin //!             };
461d0fdc396SBenno Lossin //!
462d0fdc396SBenno Lossin //!             #[allow(unreachable_code, clippy::diverging_sub_expression)]
463d0fdc396SBenno Lossin //!             if false {
464d0fdc396SBenno Lossin //!                 unsafe {
465d0fdc396SBenno Lossin //!                     ::core::ptr::write(
466d0fdc396SBenno Lossin //!                         slot,
467d0fdc396SBenno Lossin //!                         Foo {
468d0fdc396SBenno Lossin //!                             a: ::core::panic!(),
469d0fdc396SBenno Lossin //!                             b: ::core::panic!(),
470d0fdc396SBenno Lossin //!                         },
471d0fdc396SBenno Lossin //!                     );
472d0fdc396SBenno Lossin //!                 };
473d0fdc396SBenno Lossin //!             }
474d0fdc396SBenno Lossin //!             unsafe { ::kernel::init::__internal::DropGuard::forget(a) };
475d0fdc396SBenno Lossin //!             unsafe { ::kernel::init::__internal::DropGuard::forget(b) };
476d0fdc396SBenno Lossin //!         }
477d0fdc396SBenno Lossin //!         Ok(__InitOk)
478d0fdc396SBenno Lossin //!     });
479d0fdc396SBenno Lossin //!     let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> {
480d0fdc396SBenno Lossin //!         init(slot).map(|__InitOk| ())
481d0fdc396SBenno Lossin //!     };
482d0fdc396SBenno Lossin //!     let init = unsafe {
483d0fdc396SBenno Lossin //!         ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init)
484d0fdc396SBenno Lossin //!     };
485d0fdc396SBenno Lossin //!     init
486d0fdc396SBenno Lossin //! };
487d0fdc396SBenno Lossin //! ```
488d0fdc396SBenno Lossin 
489d0fdc396SBenno Lossin /// Creates a `unsafe impl<...> PinnedDrop for $type` block.
490d0fdc396SBenno Lossin ///
491d0fdc396SBenno Lossin /// See [`PinnedDrop`] for more information.
492d0fdc396SBenno Lossin #[doc(hidden)]
493d0fdc396SBenno Lossin #[macro_export]
494d0fdc396SBenno Lossin macro_rules! __pinned_drop {
495d0fdc396SBenno Lossin     (
496d0fdc396SBenno Lossin         @impl_sig($($impl_sig:tt)*),
497d0fdc396SBenno Lossin         @impl_body(
498d0fdc396SBenno Lossin             $(#[$($attr:tt)*])*
499d0fdc396SBenno Lossin             fn drop($($sig:tt)*) {
500d0fdc396SBenno Lossin                 $($inner:tt)*
501d0fdc396SBenno Lossin             }
502d0fdc396SBenno Lossin         ),
503d0fdc396SBenno Lossin     ) => {
504d0fdc396SBenno Lossin         unsafe $($impl_sig)* {
505d0fdc396SBenno Lossin             // Inherit all attributes and the type/ident tokens for the signature.
506d0fdc396SBenno Lossin             $(#[$($attr)*])*
507d0fdc396SBenno Lossin             fn drop($($sig)*, _: $crate::init::__internal::OnlyCallFromDrop) {
508d0fdc396SBenno Lossin                 $($inner)*
509d0fdc396SBenno Lossin             }
510d0fdc396SBenno Lossin         }
511d0fdc396SBenno Lossin     }
512d0fdc396SBenno Lossin }
513fc6c6baaSBenno Lossin 
514fc6c6baaSBenno Lossin /// This macro first parses the struct definition such that it separates pinned and not pinned
515fc6c6baaSBenno Lossin /// fields. Afterwards it declares the struct and implement the `PinData` trait safely.
516fc6c6baaSBenno Lossin #[doc(hidden)]
517fc6c6baaSBenno Lossin #[macro_export]
518fc6c6baaSBenno Lossin macro_rules! __pin_data {
519fc6c6baaSBenno Lossin     // Proc-macro entry point, this is supplied by the proc-macro pre-parsing.
520fc6c6baaSBenno Lossin     (parse_input:
521fc6c6baaSBenno Lossin         @args($($pinned_drop:ident)?),
522fc6c6baaSBenno Lossin         @sig(
523fc6c6baaSBenno Lossin             $(#[$($struct_attr:tt)*])*
524fc6c6baaSBenno Lossin             $vis:vis struct $name:ident
525fc6c6baaSBenno Lossin             $(where $($whr:tt)*)?
526fc6c6baaSBenno Lossin         ),
527fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
528fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
529fc6c6baaSBenno Lossin         @body({ $($fields:tt)* }),
530fc6c6baaSBenno Lossin     ) => {
531fc6c6baaSBenno Lossin         // We now use token munching to iterate through all of the fields. While doing this we
532fc6c6baaSBenno Lossin         // identify fields marked with `#[pin]`, these fields are the 'pinned fields'. The user
533fc6c6baaSBenno Lossin         // wants these to be structurally pinned. The rest of the fields are the
534fc6c6baaSBenno Lossin         // 'not pinned fields'. Additionally we collect all fields, since we need them in the right
535fc6c6baaSBenno Lossin         // order to declare the struct.
536fc6c6baaSBenno Lossin         //
537fc6c6baaSBenno Lossin         // In this call we also put some explaining comments for the parameters.
538fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
539fc6c6baaSBenno Lossin             // Attributes on the struct itself, these will just be propagated to be put onto the
540fc6c6baaSBenno Lossin             // struct definition.
541fc6c6baaSBenno Lossin             @struct_attrs($(#[$($struct_attr)*])*),
542fc6c6baaSBenno Lossin             // The visibility of the struct.
543fc6c6baaSBenno Lossin             @vis($vis),
544fc6c6baaSBenno Lossin             // The name of the struct.
545fc6c6baaSBenno Lossin             @name($name),
546fc6c6baaSBenno Lossin             // The 'impl generics', the generics that will need to be specified on the struct inside
547fc6c6baaSBenno Lossin             // of an `impl<$ty_generics>` block.
548fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
549fc6c6baaSBenno Lossin             // The 'ty generics', the generics that will need to be specified on the impl blocks.
550fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
551fc6c6baaSBenno Lossin             // The where clause of any impl block and the declaration.
552fc6c6baaSBenno Lossin             @where($($($whr)*)?),
553fc6c6baaSBenno Lossin             // The remaining fields tokens that need to be processed.
554fc6c6baaSBenno Lossin             // We add a `,` at the end to ensure correct parsing.
555fc6c6baaSBenno Lossin             @fields_munch($($fields)* ,),
556fc6c6baaSBenno Lossin             // The pinned fields.
557fc6c6baaSBenno Lossin             @pinned(),
558fc6c6baaSBenno Lossin             // The not pinned fields.
559fc6c6baaSBenno Lossin             @not_pinned(),
560fc6c6baaSBenno Lossin             // All fields.
561fc6c6baaSBenno Lossin             @fields(),
562fc6c6baaSBenno Lossin             // The accumulator containing all attributes already parsed.
563fc6c6baaSBenno Lossin             @accum(),
564fc6c6baaSBenno Lossin             // Contains `yes` or `` to indicate if `#[pin]` was found on the current field.
565fc6c6baaSBenno Lossin             @is_pinned(),
566fc6c6baaSBenno Lossin             // The proc-macro argument, this should be `PinnedDrop` or ``.
567fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
568fc6c6baaSBenno Lossin         );
569fc6c6baaSBenno Lossin     };
570fc6c6baaSBenno Lossin     (find_pinned_fields:
571fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
572fc6c6baaSBenno Lossin         @vis($vis:vis),
573fc6c6baaSBenno Lossin         @name($name:ident),
574fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
575fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
576fc6c6baaSBenno Lossin         @where($($whr:tt)*),
577fc6c6baaSBenno Lossin         // We found a PhantomPinned field, this should generally be pinned!
578fc6c6baaSBenno Lossin         @fields_munch($field:ident : $($($(::)?core::)?marker::)?PhantomPinned, $($rest:tt)*),
579fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
580fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
581fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
582fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
583fc6c6baaSBenno Lossin         // This field is not pinned.
584fc6c6baaSBenno Lossin         @is_pinned(),
585fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
586fc6c6baaSBenno Lossin     ) => {
587fc6c6baaSBenno Lossin         ::core::compile_error!(concat!(
588fc6c6baaSBenno Lossin             "The field `",
589fc6c6baaSBenno Lossin             stringify!($field),
590fc6c6baaSBenno Lossin             "` of type `PhantomPinned` only has an effect, if it has the `#[pin]` attribute.",
591fc6c6baaSBenno Lossin         ));
592fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
593fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
594fc6c6baaSBenno Lossin             @vis($vis),
595fc6c6baaSBenno Lossin             @name($name),
596fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
597fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
598fc6c6baaSBenno Lossin             @where($($whr)*),
599fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
600fc6c6baaSBenno Lossin             @pinned($($pinned)* $($accum)* $field: ::core::marker::PhantomPinned,),
601fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
602fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: ::core::marker::PhantomPinned,),
603fc6c6baaSBenno Lossin             @accum(),
604fc6c6baaSBenno Lossin             @is_pinned(),
605fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
606fc6c6baaSBenno Lossin         );
607fc6c6baaSBenno Lossin     };
608fc6c6baaSBenno Lossin     (find_pinned_fields:
609fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
610fc6c6baaSBenno Lossin         @vis($vis:vis),
611fc6c6baaSBenno Lossin         @name($name:ident),
612fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
613fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
614fc6c6baaSBenno Lossin         @where($($whr:tt)*),
615fc6c6baaSBenno Lossin         // We reached the field declaration.
616fc6c6baaSBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
617fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
618fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
619fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
620fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
621fc6c6baaSBenno Lossin         // This field is pinned.
622fc6c6baaSBenno Lossin         @is_pinned(yes),
623fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
624fc6c6baaSBenno Lossin     ) => {
625fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
626fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
627fc6c6baaSBenno Lossin             @vis($vis),
628fc6c6baaSBenno Lossin             @name($name),
629fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
630fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
631fc6c6baaSBenno Lossin             @where($($whr)*),
632fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
633fc6c6baaSBenno Lossin             @pinned($($pinned)* $($accum)* $field: $type,),
634fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
635fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
636fc6c6baaSBenno Lossin             @accum(),
637fc6c6baaSBenno Lossin             @is_pinned(),
638fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
639fc6c6baaSBenno Lossin         );
640fc6c6baaSBenno Lossin     };
641fc6c6baaSBenno Lossin     (find_pinned_fields:
642fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
643fc6c6baaSBenno Lossin         @vis($vis:vis),
644fc6c6baaSBenno Lossin         @name($name:ident),
645fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
646fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
647fc6c6baaSBenno Lossin         @where($($whr:tt)*),
648fc6c6baaSBenno Lossin         // We reached the field declaration.
649fc6c6baaSBenno Lossin         @fields_munch($field:ident : $type:ty, $($rest:tt)*),
650fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
651fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
652fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
653fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
654fc6c6baaSBenno Lossin         // This field is not pinned.
655fc6c6baaSBenno Lossin         @is_pinned(),
656fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
657fc6c6baaSBenno Lossin     ) => {
658fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
659fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
660fc6c6baaSBenno Lossin             @vis($vis),
661fc6c6baaSBenno Lossin             @name($name),
662fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
663fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
664fc6c6baaSBenno Lossin             @where($($whr)*),
665fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
666fc6c6baaSBenno Lossin             @pinned($($pinned)*),
667fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)* $($accum)* $field: $type,),
668fc6c6baaSBenno Lossin             @fields($($fields)* $($accum)* $field: $type,),
669fc6c6baaSBenno Lossin             @accum(),
670fc6c6baaSBenno Lossin             @is_pinned(),
671fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
672fc6c6baaSBenno Lossin         );
673fc6c6baaSBenno Lossin     };
674fc6c6baaSBenno Lossin     (find_pinned_fields:
675fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
676fc6c6baaSBenno Lossin         @vis($vis:vis),
677fc6c6baaSBenno Lossin         @name($name:ident),
678fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
679fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
680fc6c6baaSBenno Lossin         @where($($whr:tt)*),
681fc6c6baaSBenno Lossin         // We found the `#[pin]` attr.
682fc6c6baaSBenno Lossin         @fields_munch(#[pin] $($rest:tt)*),
683fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
684fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
685fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
686fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
687fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
688fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
689fc6c6baaSBenno Lossin     ) => {
690fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
691fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
692fc6c6baaSBenno Lossin             @vis($vis),
693fc6c6baaSBenno Lossin             @name($name),
694fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
695fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
696fc6c6baaSBenno Lossin             @where($($whr)*),
697fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
698fc6c6baaSBenno Lossin             // We do not include `#[pin]` in the list of attributes, since it is not actually an
699fc6c6baaSBenno Lossin             // attribute that is defined somewhere.
700fc6c6baaSBenno Lossin             @pinned($($pinned)*),
701fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
702fc6c6baaSBenno Lossin             @fields($($fields)*),
703fc6c6baaSBenno Lossin             @accum($($accum)*),
704fc6c6baaSBenno Lossin             // Set this to `yes`.
705fc6c6baaSBenno Lossin             @is_pinned(yes),
706fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
707fc6c6baaSBenno Lossin         );
708fc6c6baaSBenno Lossin     };
709fc6c6baaSBenno Lossin     (find_pinned_fields:
710fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
711fc6c6baaSBenno Lossin         @vis($vis:vis),
712fc6c6baaSBenno Lossin         @name($name:ident),
713fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
714fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
715fc6c6baaSBenno Lossin         @where($($whr:tt)*),
716fc6c6baaSBenno Lossin         // We reached the field declaration with visibility, for simplicity we only munch the
717fc6c6baaSBenno Lossin         // visibility and put it into `$accum`.
718fc6c6baaSBenno Lossin         @fields_munch($fvis:vis $field:ident $($rest:tt)*),
719fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
720fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
721fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
722fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
723fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
724fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
725fc6c6baaSBenno Lossin     ) => {
726fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
727fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
728fc6c6baaSBenno Lossin             @vis($vis),
729fc6c6baaSBenno Lossin             @name($name),
730fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
731fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
732fc6c6baaSBenno Lossin             @where($($whr)*),
733fc6c6baaSBenno Lossin             @fields_munch($field $($rest)*),
734fc6c6baaSBenno Lossin             @pinned($($pinned)*),
735fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
736fc6c6baaSBenno Lossin             @fields($($fields)*),
737fc6c6baaSBenno Lossin             @accum($($accum)* $fvis),
738fc6c6baaSBenno Lossin             @is_pinned($($is_pinned)?),
739fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
740fc6c6baaSBenno Lossin         );
741fc6c6baaSBenno Lossin     };
742fc6c6baaSBenno Lossin     (find_pinned_fields:
743fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
744fc6c6baaSBenno Lossin         @vis($vis:vis),
745fc6c6baaSBenno Lossin         @name($name:ident),
746fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
747fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
748fc6c6baaSBenno Lossin         @where($($whr:tt)*),
749fc6c6baaSBenno Lossin         // Some other attribute, just put it into `$accum`.
750fc6c6baaSBenno Lossin         @fields_munch(#[$($attr:tt)*] $($rest:tt)*),
751fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
752fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
753fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
754fc6c6baaSBenno Lossin         @accum($($accum:tt)*),
755fc6c6baaSBenno Lossin         @is_pinned($($is_pinned:ident)?),
756fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
757fc6c6baaSBenno Lossin     ) => {
758fc6c6baaSBenno Lossin         $crate::__pin_data!(find_pinned_fields:
759fc6c6baaSBenno Lossin             @struct_attrs($($struct_attrs)*),
760fc6c6baaSBenno Lossin             @vis($vis),
761fc6c6baaSBenno Lossin             @name($name),
762fc6c6baaSBenno Lossin             @impl_generics($($impl_generics)*),
763fc6c6baaSBenno Lossin             @ty_generics($($ty_generics)*),
764fc6c6baaSBenno Lossin             @where($($whr)*),
765fc6c6baaSBenno Lossin             @fields_munch($($rest)*),
766fc6c6baaSBenno Lossin             @pinned($($pinned)*),
767fc6c6baaSBenno Lossin             @not_pinned($($not_pinned)*),
768fc6c6baaSBenno Lossin             @fields($($fields)*),
769fc6c6baaSBenno Lossin             @accum($($accum)* #[$($attr)*]),
770fc6c6baaSBenno Lossin             @is_pinned($($is_pinned)?),
771fc6c6baaSBenno Lossin             @pinned_drop($($pinned_drop)?),
772fc6c6baaSBenno Lossin         );
773fc6c6baaSBenno Lossin     };
774fc6c6baaSBenno Lossin     (find_pinned_fields:
775fc6c6baaSBenno Lossin         @struct_attrs($($struct_attrs:tt)*),
776fc6c6baaSBenno Lossin         @vis($vis:vis),
777fc6c6baaSBenno Lossin         @name($name:ident),
778fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
779fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
780fc6c6baaSBenno Lossin         @where($($whr:tt)*),
781fc6c6baaSBenno Lossin         // We reached the end of the fields, plus an optional additional comma, since we added one
782fc6c6baaSBenno Lossin         // before and the user is also allowed to put a trailing comma.
783fc6c6baaSBenno Lossin         @fields_munch($(,)?),
784fc6c6baaSBenno Lossin         @pinned($($pinned:tt)*),
785fc6c6baaSBenno Lossin         @not_pinned($($not_pinned:tt)*),
786fc6c6baaSBenno Lossin         @fields($($fields:tt)*),
787fc6c6baaSBenno Lossin         @accum(),
788fc6c6baaSBenno Lossin         @is_pinned(),
789fc6c6baaSBenno Lossin         @pinned_drop($($pinned_drop:ident)?),
790fc6c6baaSBenno Lossin     ) => {
791fc6c6baaSBenno Lossin         // Declare the struct with all fields in the correct order.
792fc6c6baaSBenno Lossin         $($struct_attrs)*
793fc6c6baaSBenno Lossin         $vis struct $name <$($impl_generics)*>
794fc6c6baaSBenno Lossin         where $($whr)*
795fc6c6baaSBenno Lossin         {
796fc6c6baaSBenno Lossin             $($fields)*
797fc6c6baaSBenno Lossin         }
798fc6c6baaSBenno Lossin 
799fc6c6baaSBenno Lossin         // We put the rest into this const item, because it then will not be accessible to anything
800fc6c6baaSBenno Lossin         // outside.
801fc6c6baaSBenno Lossin         const _: () = {
802fc6c6baaSBenno Lossin             // We declare this struct which will host all of the projection function for our type.
803fc6c6baaSBenno Lossin             // it will be invariant over all generic parameters which are inherited from the
804fc6c6baaSBenno Lossin             // struct.
805fc6c6baaSBenno Lossin             $vis struct __ThePinData<$($impl_generics)*>
806fc6c6baaSBenno Lossin             where $($whr)*
807fc6c6baaSBenno Lossin             {
808fc6c6baaSBenno Lossin                 __phantom: ::core::marker::PhantomData<
809fc6c6baaSBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
810fc6c6baaSBenno Lossin                 >,
811fc6c6baaSBenno Lossin             }
812fc6c6baaSBenno Lossin 
813fc6c6baaSBenno Lossin             impl<$($impl_generics)*> ::core::clone::Clone for __ThePinData<$($ty_generics)*>
814fc6c6baaSBenno Lossin             where $($whr)*
815fc6c6baaSBenno Lossin             {
816fc6c6baaSBenno Lossin                 fn clone(&self) -> Self { *self }
817fc6c6baaSBenno Lossin             }
818fc6c6baaSBenno Lossin 
819fc6c6baaSBenno Lossin             impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*>
820fc6c6baaSBenno Lossin             where $($whr)*
821fc6c6baaSBenno Lossin             {}
822fc6c6baaSBenno Lossin 
823fc6c6baaSBenno Lossin             // Make all projection functions.
824fc6c6baaSBenno Lossin             $crate::__pin_data!(make_pin_data:
825fc6c6baaSBenno Lossin                 @pin_data(__ThePinData),
826fc6c6baaSBenno Lossin                 @impl_generics($($impl_generics)*),
827fc6c6baaSBenno Lossin                 @ty_generics($($ty_generics)*),
828fc6c6baaSBenno Lossin                 @where($($whr)*),
829fc6c6baaSBenno Lossin                 @pinned($($pinned)*),
830fc6c6baaSBenno Lossin                 @not_pinned($($not_pinned)*),
831fc6c6baaSBenno Lossin             );
832fc6c6baaSBenno Lossin 
833fc6c6baaSBenno Lossin             // SAFETY: We have added the correct projection functions above to `__ThePinData` and
834fc6c6baaSBenno Lossin             // we also use the least restrictive generics possible.
835fc6c6baaSBenno Lossin             unsafe impl<$($impl_generics)*>
836fc6c6baaSBenno Lossin                 $crate::init::__internal::HasPinData for $name<$($ty_generics)*>
837fc6c6baaSBenno Lossin             where $($whr)*
838fc6c6baaSBenno Lossin             {
839fc6c6baaSBenno Lossin                 type PinData = __ThePinData<$($ty_generics)*>;
840fc6c6baaSBenno Lossin 
841fc6c6baaSBenno Lossin                 unsafe fn __pin_data() -> Self::PinData {
842fc6c6baaSBenno Lossin                     __ThePinData { __phantom: ::core::marker::PhantomData }
843fc6c6baaSBenno Lossin                 }
844fc6c6baaSBenno Lossin             }
845fc6c6baaSBenno Lossin 
846fc6c6baaSBenno Lossin             unsafe impl<$($impl_generics)*>
847fc6c6baaSBenno Lossin                 $crate::init::__internal::PinData for __ThePinData<$($ty_generics)*>
848fc6c6baaSBenno Lossin             where $($whr)*
849fc6c6baaSBenno Lossin             {
850fc6c6baaSBenno Lossin                 type Datee = $name<$($ty_generics)*>;
851fc6c6baaSBenno Lossin             }
852fc6c6baaSBenno Lossin 
853fc6c6baaSBenno Lossin             // This struct will be used for the unpin analysis. Since only structurally pinned
854fc6c6baaSBenno Lossin             // fields are relevant whether the struct should implement `Unpin`.
855fc6c6baaSBenno Lossin             #[allow(dead_code)]
856fc6c6baaSBenno Lossin             struct __Unpin <'__pin, $($impl_generics)*>
857fc6c6baaSBenno Lossin             where $($whr)*
858fc6c6baaSBenno Lossin             {
859fc6c6baaSBenno Lossin                 __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>,
860fc6c6baaSBenno Lossin                 __phantom: ::core::marker::PhantomData<
861fc6c6baaSBenno Lossin                     fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*>
862fc6c6baaSBenno Lossin                 >,
863fc6c6baaSBenno Lossin                 // Only the pinned fields.
864fc6c6baaSBenno Lossin                 $($pinned)*
865fc6c6baaSBenno Lossin             }
866fc6c6baaSBenno Lossin 
867fc6c6baaSBenno Lossin             #[doc(hidden)]
868fc6c6baaSBenno Lossin             impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*>
869fc6c6baaSBenno Lossin             where
870fc6c6baaSBenno Lossin                 __Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin,
871fc6c6baaSBenno Lossin                 $($whr)*
872fc6c6baaSBenno Lossin             {}
873fc6c6baaSBenno Lossin 
874fc6c6baaSBenno Lossin             // We need to disallow normal `Drop` implementation, the exact behavior depends on
875fc6c6baaSBenno Lossin             // whether `PinnedDrop` was specified as the parameter.
876fc6c6baaSBenno Lossin             $crate::__pin_data!(drop_prevention:
877fc6c6baaSBenno Lossin                 @name($name),
878fc6c6baaSBenno Lossin                 @impl_generics($($impl_generics)*),
879fc6c6baaSBenno Lossin                 @ty_generics($($ty_generics)*),
880fc6c6baaSBenno Lossin                 @where($($whr)*),
881fc6c6baaSBenno Lossin                 @pinned_drop($($pinned_drop)?),
882fc6c6baaSBenno Lossin             );
883fc6c6baaSBenno Lossin         };
884fc6c6baaSBenno Lossin     };
885fc6c6baaSBenno Lossin     // When no `PinnedDrop` was specified, then we have to prevent implementing drop.
886fc6c6baaSBenno Lossin     (drop_prevention:
887fc6c6baaSBenno Lossin         @name($name:ident),
888fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
889fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
890fc6c6baaSBenno Lossin         @where($($whr:tt)*),
891fc6c6baaSBenno Lossin         @pinned_drop(),
892fc6c6baaSBenno Lossin     ) => {
893fc6c6baaSBenno Lossin         // We prevent this by creating a trait that will be implemented for all types implementing
894fc6c6baaSBenno Lossin         // `Drop`. Additionally we will implement this trait for the struct leading to a conflict,
895fc6c6baaSBenno Lossin         // if it also implements `Drop`
896fc6c6baaSBenno Lossin         trait MustNotImplDrop {}
897fc6c6baaSBenno Lossin         #[allow(drop_bounds)]
898fc6c6baaSBenno Lossin         impl<T: ::core::ops::Drop> MustNotImplDrop for T {}
899fc6c6baaSBenno Lossin         impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*>
900fc6c6baaSBenno Lossin         where $($whr)* {}
901d0fdc396SBenno Lossin         // We also take care to prevent users from writing a useless `PinnedDrop` implementation.
902d0fdc396SBenno Lossin         // They might implement `PinnedDrop` correctly for the struct, but forget to give
903d0fdc396SBenno Lossin         // `PinnedDrop` as the parameter to `#[pin_data]`.
904d0fdc396SBenno Lossin         #[allow(non_camel_case_types)]
905d0fdc396SBenno Lossin         trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {}
906d0fdc396SBenno Lossin         impl<T: $crate::init::PinnedDrop>
907d0fdc396SBenno Lossin             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {}
908d0fdc396SBenno Lossin         impl<$($impl_generics)*>
909d0fdc396SBenno Lossin             UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for $name<$($ty_generics)*>
910d0fdc396SBenno Lossin         where $($whr)* {}
911d0fdc396SBenno Lossin     };
912d0fdc396SBenno Lossin     // When `PinnedDrop` was specified we just implement `Drop` and delegate.
913d0fdc396SBenno Lossin     (drop_prevention:
914d0fdc396SBenno Lossin         @name($name:ident),
915d0fdc396SBenno Lossin         @impl_generics($($impl_generics:tt)*),
916d0fdc396SBenno Lossin         @ty_generics($($ty_generics:tt)*),
917d0fdc396SBenno Lossin         @where($($whr:tt)*),
918d0fdc396SBenno Lossin         @pinned_drop(PinnedDrop),
919d0fdc396SBenno Lossin     ) => {
920d0fdc396SBenno Lossin         impl<$($impl_generics)*> ::core::ops::Drop for $name<$($ty_generics)*>
921d0fdc396SBenno Lossin         where $($whr)*
922d0fdc396SBenno Lossin         {
923d0fdc396SBenno Lossin             fn drop(&mut self) {
924d0fdc396SBenno Lossin                 // SAFETY: Since this is a destructor, `self` will not move after this function
925d0fdc396SBenno Lossin                 // terminates, since it is inaccessible.
926d0fdc396SBenno Lossin                 let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) };
927d0fdc396SBenno Lossin                 // SAFETY: Since this is a drop function, we can create this token to call the
928d0fdc396SBenno Lossin                 // pinned destructor of this type.
929d0fdc396SBenno Lossin                 let token = unsafe { $crate::init::__internal::OnlyCallFromDrop::new() };
930d0fdc396SBenno Lossin                 $crate::init::PinnedDrop::drop(pinned, token);
931d0fdc396SBenno Lossin             }
932d0fdc396SBenno Lossin         }
933fc6c6baaSBenno Lossin     };
934fc6c6baaSBenno Lossin     // If some other parameter was specified, we emit a readable error.
935fc6c6baaSBenno Lossin     (drop_prevention:
936fc6c6baaSBenno Lossin         @name($name:ident),
937fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
938fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
939fc6c6baaSBenno Lossin         @where($($whr:tt)*),
940fc6c6baaSBenno Lossin         @pinned_drop($($rest:tt)*),
941fc6c6baaSBenno Lossin     ) => {
942fc6c6baaSBenno Lossin         compile_error!(
943fc6c6baaSBenno Lossin             "Wrong parameters to `#[pin_data]`, expected nothing or `PinnedDrop`, got '{}'.",
944fc6c6baaSBenno Lossin             stringify!($($rest)*),
945fc6c6baaSBenno Lossin         );
946fc6c6baaSBenno Lossin     };
947fc6c6baaSBenno Lossin     (make_pin_data:
948fc6c6baaSBenno Lossin         @pin_data($pin_data:ident),
949fc6c6baaSBenno Lossin         @impl_generics($($impl_generics:tt)*),
950fc6c6baaSBenno Lossin         @ty_generics($($ty_generics:tt)*),
951fc6c6baaSBenno Lossin         @where($($whr:tt)*),
952fc6c6baaSBenno Lossin         @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
953fc6c6baaSBenno Lossin         @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
954fc6c6baaSBenno Lossin     ) => {
955fc6c6baaSBenno Lossin         // For every field, we create a projection function according to its projection type. If a
956fc6c6baaSBenno Lossin         // field is structurally pinned, then it must be initialized via `PinInit`, if it is not
957fc6c6baaSBenno Lossin         // structurally pinned, then it can be initialized via `Init`.
958fc6c6baaSBenno Lossin         //
959fc6c6baaSBenno Lossin         // The functions are `unsafe` to prevent accidentally calling them.
960fc6c6baaSBenno Lossin         #[allow(dead_code)]
961fc6c6baaSBenno Lossin         impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
962fc6c6baaSBenno Lossin         where $($whr)*
963fc6c6baaSBenno Lossin         {
964fc6c6baaSBenno Lossin             $(
965*f8badd15SBenno Lossin                 $(#[$($p_attr)*])*
966fc6c6baaSBenno Lossin                 $pvis unsafe fn $p_field<E>(
967fc6c6baaSBenno Lossin                     self,
968fc6c6baaSBenno Lossin                     slot: *mut $p_type,
969fc6c6baaSBenno Lossin                     init: impl $crate::init::PinInit<$p_type, E>,
970fc6c6baaSBenno Lossin                 ) -> ::core::result::Result<(), E> {
971fc6c6baaSBenno Lossin                     unsafe { $crate::init::PinInit::__pinned_init(init, slot) }
972fc6c6baaSBenno Lossin                 }
973fc6c6baaSBenno Lossin             )*
974fc6c6baaSBenno Lossin             $(
975*f8badd15SBenno Lossin                 $(#[$($attr)*])*
976fc6c6baaSBenno Lossin                 $fvis unsafe fn $field<E>(
977fc6c6baaSBenno Lossin                     self,
978fc6c6baaSBenno Lossin                     slot: *mut $type,
979fc6c6baaSBenno Lossin                     init: impl $crate::init::Init<$type, E>,
980fc6c6baaSBenno Lossin                 ) -> ::core::result::Result<(), E> {
981fc6c6baaSBenno Lossin                     unsafe { $crate::init::Init::__init(init, slot) }
982fc6c6baaSBenno Lossin                 }
983fc6c6baaSBenno Lossin             )*
984fc6c6baaSBenno Lossin         }
985fc6c6baaSBenno Lossin     };
986fc6c6baaSBenno Lossin }
987b3068ac3SBenno Lossin 
988b3068ac3SBenno Lossin /// The internal init macro. Do not call manually!
989b3068ac3SBenno Lossin ///
990b3068ac3SBenno Lossin /// This is called by the `{try_}{pin_}init!` macros with various inputs.
991b3068ac3SBenno Lossin ///
992b3068ac3SBenno Lossin /// This macro has multiple internal call configurations, these are always the very first ident:
993b3068ac3SBenno Lossin /// - nothing: this is the base case and called by the `{try_}{pin_}init!` macros.
994b3068ac3SBenno Lossin /// - `init_slot`: recursively creates the code that initializes all fields in `slot`.
995b3068ac3SBenno Lossin /// - `make_initializer`: recursively create the struct initializer that guarantees that every
996b3068ac3SBenno Lossin ///   field has been initialized exactly once.
997b3068ac3SBenno Lossin /// - `forget_guards`: recursively forget the drop guards for every field.
998b3068ac3SBenno Lossin #[doc(hidden)]
999b3068ac3SBenno Lossin #[macro_export]
1000b3068ac3SBenno Lossin macro_rules! __init_internal {
1001b3068ac3SBenno Lossin     (
1002b3068ac3SBenno Lossin         @this($($this:ident)?),
1003b3068ac3SBenno Lossin         @typ($t:ident $(::<$($generics:ty),*>)?),
1004b3068ac3SBenno Lossin         @fields($($fields:tt)*),
1005b3068ac3SBenno Lossin         @error($err:ty),
1006b3068ac3SBenno Lossin         // Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
1007b3068ac3SBenno Lossin         // case.
1008b3068ac3SBenno Lossin         @data($data:ident, $($use_data:ident)?),
1009b3068ac3SBenno Lossin         // `HasPinData` or `HasInitData`.
1010b3068ac3SBenno Lossin         @has_data($has_data:ident, $get_data:ident),
1011b3068ac3SBenno Lossin         // `pin_init_from_closure` or `init_from_closure`.
1012b3068ac3SBenno Lossin         @construct_closure($construct_closure:ident),
1013b3068ac3SBenno Lossin     ) => {{
1014b3068ac3SBenno Lossin         // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
1015b3068ac3SBenno Lossin         // type and shadow it later when we insert the arbitrary user code. That way there will be
1016b3068ac3SBenno Lossin         // no possibility of returning without `unsafe`.
1017b3068ac3SBenno Lossin         struct __InitOk;
1018b3068ac3SBenno Lossin         // Get the data about fields from the supplied type.
1019b3068ac3SBenno Lossin         let data = unsafe {
1020b3068ac3SBenno Lossin             use $crate::init::__internal::$has_data;
1021b3068ac3SBenno Lossin             $t$(::<$($generics),*>)?::$get_data()
1022b3068ac3SBenno Lossin         };
1023b3068ac3SBenno Lossin         // Ensure that `data` really is of type `$data` and help with type inference:
1024b3068ac3SBenno Lossin         let init = $crate::init::__internal::$data::make_closure::<_, __InitOk, $err>(
1025b3068ac3SBenno Lossin             data,
1026b3068ac3SBenno Lossin             move |slot| {
1027b3068ac3SBenno Lossin                 {
1028b3068ac3SBenno Lossin                     // Shadow the structure so it cannot be used to return early.
1029b3068ac3SBenno Lossin                     struct __InitOk;
1030b3068ac3SBenno Lossin                     // Create the `this` so it can be referenced by the user inside of the
1031b3068ac3SBenno Lossin                     // expressions creating the individual fields.
1032b3068ac3SBenno Lossin                     $(let $this = unsafe { ::core::ptr::NonNull::new_unchecked(slot) };)?
1033b3068ac3SBenno Lossin                     // Initialize every field.
1034b3068ac3SBenno Lossin                     $crate::__init_internal!(init_slot($($use_data)?):
1035b3068ac3SBenno Lossin                         @data(data),
1036b3068ac3SBenno Lossin                         @slot(slot),
1037b3068ac3SBenno Lossin                         @munch_fields($($fields)*,),
1038b3068ac3SBenno Lossin                     );
1039b3068ac3SBenno Lossin                     // We use unreachable code to ensure that all fields have been mentioned exactly
1040b3068ac3SBenno Lossin                     // once, this struct initializer will still be type-checked and complain with a
1041b3068ac3SBenno Lossin                     // very natural error message if a field is forgotten/mentioned more than once.
1042b3068ac3SBenno Lossin                     #[allow(unreachable_code, clippy::diverging_sub_expression)]
1043b3068ac3SBenno Lossin                     if false {
1044b3068ac3SBenno Lossin                         $crate::__init_internal!(make_initializer:
1045b3068ac3SBenno Lossin                             @slot(slot),
1046b3068ac3SBenno Lossin                             @type_name($t),
1047b3068ac3SBenno Lossin                             @munch_fields($($fields)*,),
1048b3068ac3SBenno Lossin                             @acc(),
1049b3068ac3SBenno Lossin                         );
1050b3068ac3SBenno Lossin                     }
1051b3068ac3SBenno Lossin                     // Forget all guards, since initialization was a success.
1052b3068ac3SBenno Lossin                     $crate::__init_internal!(forget_guards:
1053b3068ac3SBenno Lossin                         @munch_fields($($fields)*,),
1054b3068ac3SBenno Lossin                     );
1055b3068ac3SBenno Lossin                 }
1056b3068ac3SBenno Lossin                 Ok(__InitOk)
1057b3068ac3SBenno Lossin             }
1058b3068ac3SBenno Lossin         );
1059b3068ac3SBenno Lossin         let init = move |slot| -> ::core::result::Result<(), $err> {
1060b3068ac3SBenno Lossin             init(slot).map(|__InitOk| ())
1061b3068ac3SBenno Lossin         };
1062b3068ac3SBenno Lossin         let init = unsafe { $crate::init::$construct_closure::<_, $err>(init) };
1063b3068ac3SBenno Lossin         init
1064b3068ac3SBenno Lossin     }};
1065b3068ac3SBenno Lossin     (init_slot($($use_data:ident)?):
1066b3068ac3SBenno Lossin         @data($data:ident),
1067b3068ac3SBenno Lossin         @slot($slot:ident),
1068b3068ac3SBenno Lossin         @munch_fields($(,)?),
1069b3068ac3SBenno Lossin     ) => {
1070b3068ac3SBenno Lossin         // Endpoint of munching, no fields are left.
1071b3068ac3SBenno Lossin     };
1072b3068ac3SBenno Lossin     (init_slot($use_data:ident): // `use_data` is present, so we use the `data` to init fields.
1073b3068ac3SBenno Lossin         @data($data:ident),
1074b3068ac3SBenno Lossin         @slot($slot:ident),
1075b3068ac3SBenno Lossin         // In-place initialization syntax.
1076b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1077b3068ac3SBenno Lossin     ) => {
1078b3068ac3SBenno Lossin         let $field = $val;
1079b3068ac3SBenno Lossin         // Call the initializer.
1080b3068ac3SBenno Lossin         //
1081b3068ac3SBenno Lossin         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1082b3068ac3SBenno Lossin         // return when an error/panic occurs.
1083b3068ac3SBenno Lossin         // We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
1084b3068ac3SBenno Lossin         unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), $field)? };
1085b3068ac3SBenno Lossin         // Create the drop guard.
1086b3068ac3SBenno Lossin         //
1087b3068ac3SBenno Lossin         // We only give access to `&DropGuard`, so it cannot be forgotten via safe code.
1088b3068ac3SBenno Lossin         //
1089b3068ac3SBenno Lossin         // SAFETY: We forget the guard later when initialization has succeeded.
1090b3068ac3SBenno Lossin         let $field = &unsafe {
1091b3068ac3SBenno Lossin             $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1092b3068ac3SBenno Lossin         };
1093b3068ac3SBenno Lossin 
1094b3068ac3SBenno Lossin         $crate::__init_internal!(init_slot($use_data):
1095b3068ac3SBenno Lossin             @data($data),
1096b3068ac3SBenno Lossin             @slot($slot),
1097b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1098b3068ac3SBenno Lossin         );
1099b3068ac3SBenno Lossin     };
1100b3068ac3SBenno Lossin     (init_slot(): // No `use_data`, so we use `Init::__init` directly.
1101b3068ac3SBenno Lossin         @data($data:ident),
1102b3068ac3SBenno Lossin         @slot($slot:ident),
1103b3068ac3SBenno Lossin         // In-place initialization syntax.
1104b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1105b3068ac3SBenno Lossin     ) => {
1106b3068ac3SBenno Lossin         let $field = $val;
1107b3068ac3SBenno Lossin         // Call the initializer.
1108b3068ac3SBenno Lossin         //
1109b3068ac3SBenno Lossin         // SAFETY: `slot` is valid, because we are inside of an initializer closure, we
1110b3068ac3SBenno Lossin         // return when an error/panic occurs.
1111b3068ac3SBenno Lossin         unsafe { $crate::init::Init::__init($field, ::core::ptr::addr_of_mut!((*$slot).$field))? };
1112b3068ac3SBenno Lossin         // Create the drop guard.
1113b3068ac3SBenno Lossin         //
1114b3068ac3SBenno Lossin         // We only give access to `&DropGuard`, so it cannot be forgotten via safe code.
1115b3068ac3SBenno Lossin         //
1116b3068ac3SBenno Lossin         // SAFETY: We forget the guard later when initialization has succeeded.
1117b3068ac3SBenno Lossin         let $field = &unsafe {
1118b3068ac3SBenno Lossin             $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1119b3068ac3SBenno Lossin         };
1120b3068ac3SBenno Lossin 
1121b3068ac3SBenno Lossin         $crate::__init_internal!(init_slot():
1122b3068ac3SBenno Lossin             @data($data),
1123b3068ac3SBenno Lossin             @slot($slot),
1124b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1125b3068ac3SBenno Lossin         );
1126b3068ac3SBenno Lossin     };
1127b3068ac3SBenno Lossin     (init_slot($($use_data:ident)?):
1128b3068ac3SBenno Lossin         @data($data:ident),
1129b3068ac3SBenno Lossin         @slot($slot:ident),
1130b3068ac3SBenno Lossin         // Init by-value.
1131b3068ac3SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1132b3068ac3SBenno Lossin     ) => {
1133b3068ac3SBenno Lossin         $(let $field = $val;)?
1134b3068ac3SBenno Lossin         // Initialize the field.
1135b3068ac3SBenno Lossin         //
1136b3068ac3SBenno Lossin         // SAFETY: The memory at `slot` is uninitialized.
1137b3068ac3SBenno Lossin         unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
1138b3068ac3SBenno Lossin         // Create the drop guard:
1139b3068ac3SBenno Lossin         //
1140b3068ac3SBenno Lossin         // We only give access to `&DropGuard`, so it cannot be accidentally forgotten.
1141b3068ac3SBenno Lossin         //
1142b3068ac3SBenno Lossin         // SAFETY: We forget the guard later when initialization has succeeded.
1143b3068ac3SBenno Lossin         let $field = &unsafe {
1144b3068ac3SBenno Lossin             $crate::init::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1145b3068ac3SBenno Lossin         };
1146b3068ac3SBenno Lossin 
1147b3068ac3SBenno Lossin         $crate::__init_internal!(init_slot($($use_data)?):
1148b3068ac3SBenno Lossin             @data($data),
1149b3068ac3SBenno Lossin             @slot($slot),
1150b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1151b3068ac3SBenno Lossin         );
1152b3068ac3SBenno Lossin     };
1153b3068ac3SBenno Lossin     (make_initializer:
1154b3068ac3SBenno Lossin         @slot($slot:ident),
1155b3068ac3SBenno Lossin         @type_name($t:ident),
1156b3068ac3SBenno Lossin         @munch_fields($(,)?),
1157b3068ac3SBenno Lossin         @acc($($acc:tt)*),
1158b3068ac3SBenno Lossin     ) => {
1159b3068ac3SBenno Lossin         // Endpoint, nothing more to munch, create the initializer.
1160b3068ac3SBenno Lossin         // Since we are in the `if false` branch, this will never get executed. We abuse `slot` to
1161b3068ac3SBenno Lossin         // get the correct type inference here:
1162b3068ac3SBenno Lossin         unsafe {
1163b3068ac3SBenno Lossin             ::core::ptr::write($slot, $t {
1164b3068ac3SBenno Lossin                 $($acc)*
1165b3068ac3SBenno Lossin             });
1166b3068ac3SBenno Lossin         }
1167b3068ac3SBenno Lossin     };
1168b3068ac3SBenno Lossin     (make_initializer:
1169b3068ac3SBenno Lossin         @slot($slot:ident),
1170b3068ac3SBenno Lossin         @type_name($t:ident),
1171b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1172b3068ac3SBenno Lossin         @acc($($acc:tt)*),
1173b3068ac3SBenno Lossin     ) => {
1174b3068ac3SBenno Lossin         $crate::__init_internal!(make_initializer:
1175b3068ac3SBenno Lossin             @slot($slot),
1176b3068ac3SBenno Lossin             @type_name($t),
1177b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1178b3068ac3SBenno Lossin             @acc($($acc)* $field: ::core::panic!(),),
1179b3068ac3SBenno Lossin         );
1180b3068ac3SBenno Lossin     };
1181b3068ac3SBenno Lossin     (make_initializer:
1182b3068ac3SBenno Lossin         @slot($slot:ident),
1183b3068ac3SBenno Lossin         @type_name($t:ident),
1184b3068ac3SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1185b3068ac3SBenno Lossin         @acc($($acc:tt)*),
1186b3068ac3SBenno Lossin     ) => {
1187b3068ac3SBenno Lossin         $crate::__init_internal!(make_initializer:
1188b3068ac3SBenno Lossin             @slot($slot),
1189b3068ac3SBenno Lossin             @type_name($t),
1190b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1191b3068ac3SBenno Lossin             @acc($($acc)* $field: ::core::panic!(),),
1192b3068ac3SBenno Lossin         );
1193b3068ac3SBenno Lossin     };
1194b3068ac3SBenno Lossin     (forget_guards:
1195b3068ac3SBenno Lossin         @munch_fields($(,)?),
1196b3068ac3SBenno Lossin     ) => {
1197b3068ac3SBenno Lossin         // Munching finished.
1198b3068ac3SBenno Lossin     };
1199b3068ac3SBenno Lossin     (forget_guards:
1200b3068ac3SBenno Lossin         @munch_fields($field:ident <- $val:expr, $($rest:tt)*),
1201b3068ac3SBenno Lossin     ) => {
1202b3068ac3SBenno Lossin         unsafe { $crate::init::__internal::DropGuard::forget($field) };
1203b3068ac3SBenno Lossin 
1204b3068ac3SBenno Lossin         $crate::__init_internal!(forget_guards:
1205b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1206b3068ac3SBenno Lossin         );
1207b3068ac3SBenno Lossin     };
1208b3068ac3SBenno Lossin     (forget_guards:
1209b3068ac3SBenno Lossin         @munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1210b3068ac3SBenno Lossin     ) => {
1211b3068ac3SBenno Lossin         unsafe { $crate::init::__internal::DropGuard::forget($field) };
1212b3068ac3SBenno Lossin 
1213b3068ac3SBenno Lossin         $crate::__init_internal!(forget_guards:
1214b3068ac3SBenno Lossin             @munch_fields($($rest)*),
1215b3068ac3SBenno Lossin         );
1216b3068ac3SBenno Lossin     };
1217b3068ac3SBenno Lossin }
1218