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 4fc6c6baaSBenno Lossin //! `pinned_drop`. 5fc6c6baaSBenno Lossin //! 6fc6c6baaSBenno Lossin //! These macros should never be called directly, since they expect their input to be 7fc6c6baaSBenno Lossin //! in a certain format which is internal. Use the proc-macros instead. 8fc6c6baaSBenno Lossin //! 9fc6c6baaSBenno Lossin //! This architecture has been chosen because the kernel does not yet have access to `syn` which 10fc6c6baaSBenno Lossin //! would make matters a lot easier for implementing these as proc-macros. 11fc6c6baaSBenno Lossin //! 12fc6c6baaSBenno Lossin //! # Macro expansion example 13fc6c6baaSBenno Lossin //! 14fc6c6baaSBenno Lossin //! This section is intended for readers trying to understand the macros in this module and the 15fc6c6baaSBenno Lossin //! `pin_init!` macros from `init.rs`. 16fc6c6baaSBenno Lossin //! 17fc6c6baaSBenno Lossin //! We will look at the following example: 18fc6c6baaSBenno Lossin //! 19*309786c2SBenno Lossin //! ```rust,ignore 20fc6c6baaSBenno Lossin //! # use kernel::init::*; 21*309786c2SBenno Lossin //! # use core::pin::Pin; 22fc6c6baaSBenno Lossin //! #[pin_data] 23fc6c6baaSBenno Lossin //! #[repr(C)] 24fc6c6baaSBenno Lossin //! struct Bar<T> { 25fc6c6baaSBenno Lossin //! #[pin] 26fc6c6baaSBenno Lossin //! t: T, 27fc6c6baaSBenno Lossin //! pub x: usize, 28fc6c6baaSBenno Lossin //! } 29fc6c6baaSBenno Lossin //! 30fc6c6baaSBenno Lossin //! impl<T> Bar<T> { 31fc6c6baaSBenno Lossin //! fn new(t: T) -> impl PinInit<Self> { 32fc6c6baaSBenno Lossin //! pin_init!(Self { t, x: 0 }) 33fc6c6baaSBenno Lossin //! } 34fc6c6baaSBenno Lossin //! } 35d0fdc396SBenno Lossin //! 36d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)] 37d0fdc396SBenno Lossin //! struct Foo { 38d0fdc396SBenno Lossin //! a: usize, 39d0fdc396SBenno Lossin //! #[pin] 40d0fdc396SBenno Lossin //! b: Bar<u32>, 41d0fdc396SBenno Lossin //! } 42d0fdc396SBenno Lossin //! 43d0fdc396SBenno Lossin //! #[pinned_drop] 44d0fdc396SBenno Lossin //! impl PinnedDrop for Foo { 45d0fdc396SBenno Lossin //! fn drop(self: Pin<&mut Self>) { 46d0fdc396SBenno Lossin //! println!("{self:p} is getting dropped."); 47d0fdc396SBenno Lossin //! } 48d0fdc396SBenno Lossin //! } 49d0fdc396SBenno Lossin //! 50d0fdc396SBenno Lossin //! let a = 42; 51d0fdc396SBenno Lossin //! let initializer = pin_init!(Foo { 52d0fdc396SBenno Lossin //! a, 53d0fdc396SBenno Lossin //! b <- Bar::new(36), 54d0fdc396SBenno Lossin //! }); 55fc6c6baaSBenno Lossin //! ``` 56fc6c6baaSBenno Lossin //! 57fc6c6baaSBenno Lossin //! This example includes the most common and important features of the pin-init API. 58fc6c6baaSBenno Lossin //! 59fc6c6baaSBenno Lossin //! Below you can find individual section about the different macro invocations. Here are some 60fc6c6baaSBenno Lossin //! general things we need to take into account when designing macros: 61fc6c6baaSBenno Lossin //! - use global paths, similarly to file paths, these start with the separator: `::core::panic!()` 62fc6c6baaSBenno Lossin //! this ensures that the correct item is used, since users could define their own `mod core {}` 63fc6c6baaSBenno Lossin //! and then their own `panic!` inside to execute arbitrary code inside of our macro. 64fc6c6baaSBenno Lossin //! - macro `unsafe` hygiene: we need to ensure that we do not expand arbitrary, user-supplied 65fc6c6baaSBenno Lossin //! expressions inside of an `unsafe` block in the macro, because this would allow users to do 66fc6c6baaSBenno Lossin //! `unsafe` operations without an associated `unsafe` block. 67fc6c6baaSBenno Lossin //! 68fc6c6baaSBenno Lossin //! ## `#[pin_data]` on `Bar` 69fc6c6baaSBenno Lossin //! 70fc6c6baaSBenno Lossin //! This macro is used to specify which fields are structurally pinned and which fields are not. It 71fc6c6baaSBenno Lossin //! is placed on the struct definition and allows `#[pin]` to be placed on the fields. 72fc6c6baaSBenno Lossin //! 73fc6c6baaSBenno Lossin //! Here is the definition of `Bar` from our example: 74fc6c6baaSBenno Lossin //! 75*309786c2SBenno Lossin //! ```rust,ignore 76fc6c6baaSBenno Lossin //! # use kernel::init::*; 77fc6c6baaSBenno Lossin //! #[pin_data] 78fc6c6baaSBenno Lossin //! #[repr(C)] 79fc6c6baaSBenno Lossin //! struct Bar<T> { 80*309786c2SBenno Lossin //! #[pin] 81fc6c6baaSBenno Lossin //! t: T, 82fc6c6baaSBenno Lossin //! pub x: usize, 83fc6c6baaSBenno Lossin //! } 84fc6c6baaSBenno Lossin //! ``` 85fc6c6baaSBenno Lossin //! 86fc6c6baaSBenno Lossin //! This expands to the following code: 87fc6c6baaSBenno Lossin //! 88*309786c2SBenno Lossin //! ```rust,ignore 89fc6c6baaSBenno Lossin //! // Firstly the normal definition of the struct, attributes are preserved: 90fc6c6baaSBenno Lossin //! #[repr(C)] 91fc6c6baaSBenno Lossin //! struct Bar<T> { 92fc6c6baaSBenno Lossin //! t: T, 93fc6c6baaSBenno Lossin //! pub x: usize, 94fc6c6baaSBenno Lossin //! } 95fc6c6baaSBenno Lossin //! // Then an anonymous constant is defined, this is because we do not want any code to access the 96fc6c6baaSBenno Lossin //! // types that we define inside: 97fc6c6baaSBenno Lossin //! const _: () = { 98fc6c6baaSBenno Lossin //! // We define the pin-data carrying struct, it is a ZST and needs to have the same generics, 99fc6c6baaSBenno Lossin //! // since we need to implement access functions for each field and thus need to know its 100fc6c6baaSBenno Lossin //! // type. 101fc6c6baaSBenno Lossin //! struct __ThePinData<T> { 102fc6c6baaSBenno Lossin //! __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>, 103fc6c6baaSBenno Lossin //! } 104fc6c6baaSBenno Lossin //! // We implement `Copy` for the pin-data struct, since all functions it defines will take 105fc6c6baaSBenno Lossin //! // `self` by value. 106fc6c6baaSBenno Lossin //! impl<T> ::core::clone::Clone for __ThePinData<T> { 107fc6c6baaSBenno Lossin //! fn clone(&self) -> Self { 108fc6c6baaSBenno Lossin //! *self 109fc6c6baaSBenno Lossin //! } 110fc6c6baaSBenno Lossin //! } 111fc6c6baaSBenno Lossin //! impl<T> ::core::marker::Copy for __ThePinData<T> {} 112fc6c6baaSBenno Lossin //! // For every field of `Bar`, the pin-data struct will define a function with the same name 113fc6c6baaSBenno Lossin //! // and accessor (`pub` or `pub(crate)` etc.). This function will take a pointer to the 114fc6c6baaSBenno Lossin //! // field (`slot`) and a `PinInit` or `Init` depending on the projection kind of the field 115fc6c6baaSBenno Lossin //! // (if pinning is structural for the field, then `PinInit` otherwise `Init`). 116fc6c6baaSBenno Lossin //! #[allow(dead_code)] 117fc6c6baaSBenno Lossin //! impl<T> __ThePinData<T> { 118fc6c6baaSBenno Lossin //! unsafe fn t<E>( 119fc6c6baaSBenno Lossin //! self, 120fc6c6baaSBenno Lossin //! slot: *mut T, 121*309786c2SBenno Lossin //! // Since `t` is `#[pin]`, this is `PinInit`. 122*309786c2SBenno Lossin //! init: impl ::kernel::init::PinInit<T, E>, 123fc6c6baaSBenno Lossin //! ) -> ::core::result::Result<(), E> { 124*309786c2SBenno Lossin //! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) } 125fc6c6baaSBenno Lossin //! } 126fc6c6baaSBenno Lossin //! pub unsafe fn x<E>( 127fc6c6baaSBenno Lossin //! self, 128fc6c6baaSBenno Lossin //! slot: *mut usize, 129*309786c2SBenno Lossin //! // Since `x` is not `#[pin]`, this is `Init`. 130fc6c6baaSBenno Lossin //! init: impl ::kernel::init::Init<usize, E>, 131fc6c6baaSBenno Lossin //! ) -> ::core::result::Result<(), E> { 132fc6c6baaSBenno Lossin //! unsafe { ::kernel::init::Init::__init(init, slot) } 133fc6c6baaSBenno Lossin //! } 134fc6c6baaSBenno Lossin //! } 135fc6c6baaSBenno Lossin //! // Implement the internal `HasPinData` trait that associates `Bar` with the pin-data struct 136*309786c2SBenno Lossin //! // that we constructed above. 137fc6c6baaSBenno Lossin //! unsafe impl<T> ::kernel::init::__internal::HasPinData for Bar<T> { 138fc6c6baaSBenno Lossin //! type PinData = __ThePinData<T>; 139fc6c6baaSBenno Lossin //! unsafe fn __pin_data() -> Self::PinData { 140fc6c6baaSBenno Lossin //! __ThePinData { 141fc6c6baaSBenno Lossin //! __phantom: ::core::marker::PhantomData, 142fc6c6baaSBenno Lossin //! } 143fc6c6baaSBenno Lossin //! } 144fc6c6baaSBenno Lossin //! } 145fc6c6baaSBenno Lossin //! // Implement the internal `PinData` trait that marks the pin-data struct as a pin-data 146fc6c6baaSBenno Lossin //! // struct. This is important to ensure that no user can implement a rouge `__pin_data` 147fc6c6baaSBenno Lossin //! // function without using `unsafe`. 148fc6c6baaSBenno Lossin //! unsafe impl<T> ::kernel::init::__internal::PinData for __ThePinData<T> { 149fc6c6baaSBenno Lossin //! type Datee = Bar<T>; 150fc6c6baaSBenno Lossin //! } 151fc6c6baaSBenno Lossin //! // Now we only want to implement `Unpin` for `Bar` when every structurally pinned field is 152fc6c6baaSBenno Lossin //! // `Unpin`. In other words, whether `Bar` is `Unpin` only depends on structurally pinned 153fc6c6baaSBenno Lossin //! // fields (those marked with `#[pin]`). These fields will be listed in this struct, in our 154fc6c6baaSBenno Lossin //! // case no such fields exist, hence this is almost empty. The two phantomdata fields exist 155fc6c6baaSBenno Lossin //! // for two reasons: 156fc6c6baaSBenno Lossin //! // - `__phantom`: every generic must be used, since we cannot really know which generics 157fc6c6baaSBenno Lossin //! // are used, we declere all and then use everything here once. 158fc6c6baaSBenno Lossin //! // - `__phantom_pin`: uses the `'__pin` lifetime and ensures that this struct is invariant 159fc6c6baaSBenno Lossin //! // over it. The lifetime is needed to work around the limitation that trait bounds must 160fc6c6baaSBenno Lossin //! // not be trivial, e.g. the user has a `#[pin] PhantomPinned` field -- this is 161fc6c6baaSBenno Lossin //! // unconditionally `!Unpin` and results in an error. The lifetime tricks the compiler 162fc6c6baaSBenno Lossin //! // into accepting these bounds regardless. 163fc6c6baaSBenno Lossin //! #[allow(dead_code)] 164fc6c6baaSBenno Lossin //! struct __Unpin<'__pin, T> { 165fc6c6baaSBenno Lossin //! __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>, 166fc6c6baaSBenno Lossin //! __phantom: ::core::marker::PhantomData<fn(Bar<T>) -> Bar<T>>, 167*309786c2SBenno Lossin //! // Our only `#[pin]` field is `t`. 168*309786c2SBenno Lossin //! t: T, 169fc6c6baaSBenno Lossin //! } 170fc6c6baaSBenno Lossin //! #[doc(hidden)] 171fc6c6baaSBenno Lossin //! impl<'__pin, T> 172fc6c6baaSBenno Lossin //! ::core::marker::Unpin for Bar<T> where __Unpin<'__pin, T>: ::core::marker::Unpin {} 173fc6c6baaSBenno Lossin //! // Now we need to ensure that `Bar` does not implement `Drop`, since that would give users 174fc6c6baaSBenno Lossin //! // access to `&mut self` inside of `drop` even if the struct was pinned. This could lead to 175fc6c6baaSBenno Lossin //! // UB with only safe code, so we disallow this by giving a trait implementation error using 176fc6c6baaSBenno Lossin //! // a direct impl and a blanket implementation. 177fc6c6baaSBenno Lossin //! trait MustNotImplDrop {} 178fc6c6baaSBenno Lossin //! // Normally `Drop` bounds do not have the correct semantics, but for this purpose they do 179fc6c6baaSBenno Lossin //! // (normally people want to know if a type has any kind of drop glue at all, here we want 180fc6c6baaSBenno Lossin //! // to know if it has any kind of custom drop glue, which is exactly what this bound does). 181fc6c6baaSBenno Lossin //! #[allow(drop_bounds)] 182fc6c6baaSBenno Lossin //! impl<T: ::core::ops::Drop> MustNotImplDrop for T {} 183fc6c6baaSBenno Lossin //! impl<T> MustNotImplDrop for Bar<T> {} 184d0fdc396SBenno Lossin //! // Here comes a convenience check, if one implemented `PinnedDrop`, but forgot to add it to 185d0fdc396SBenno Lossin //! // `#[pin_data]`, then this will error with the same mechanic as above, this is not needed 186d0fdc396SBenno Lossin //! // for safety, but a good sanity check, since no normal code calls `PinnedDrop::drop`. 187d0fdc396SBenno Lossin //! #[allow(non_camel_case_types)] 188d0fdc396SBenno Lossin //! trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {} 189d0fdc396SBenno Lossin //! impl<T: ::kernel::init::PinnedDrop> 190d0fdc396SBenno Lossin //! UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} 191d0fdc396SBenno Lossin //! impl<T> UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for Bar<T> {} 192fc6c6baaSBenno Lossin //! }; 193fc6c6baaSBenno Lossin //! ``` 194fc6c6baaSBenno Lossin //! 195fc6c6baaSBenno Lossin //! ## `pin_init!` in `impl Bar` 196fc6c6baaSBenno Lossin //! 197fc6c6baaSBenno Lossin //! This macro creates an pin-initializer for the given struct. It requires that the struct is 198fc6c6baaSBenno Lossin //! annotated by `#[pin_data]`. 199fc6c6baaSBenno Lossin //! 200fc6c6baaSBenno Lossin //! Here is the impl on `Bar` defining the new function: 201fc6c6baaSBenno Lossin //! 202*309786c2SBenno Lossin //! ```rust,ignore 203fc6c6baaSBenno Lossin //! impl<T> Bar<T> { 204fc6c6baaSBenno Lossin //! fn new(t: T) -> impl PinInit<Self> { 205fc6c6baaSBenno Lossin //! pin_init!(Self { t, x: 0 }) 206fc6c6baaSBenno Lossin //! } 207fc6c6baaSBenno Lossin //! } 208fc6c6baaSBenno Lossin //! ``` 209fc6c6baaSBenno Lossin //! 210fc6c6baaSBenno Lossin //! This expands to the following code: 211fc6c6baaSBenno Lossin //! 212*309786c2SBenno Lossin //! ```rust,ignore 213fc6c6baaSBenno Lossin //! impl<T> Bar<T> { 214fc6c6baaSBenno Lossin //! fn new(t: T) -> impl PinInit<Self> { 215fc6c6baaSBenno Lossin //! { 216fc6c6baaSBenno Lossin //! // We do not want to allow arbitrary returns, so we declare this type as the `Ok` 217fc6c6baaSBenno Lossin //! // return type and shadow it later when we insert the arbitrary user code. That way 218fc6c6baaSBenno Lossin //! // there will be no possibility of returning without `unsafe`. 219fc6c6baaSBenno Lossin //! struct __InitOk; 220fc6c6baaSBenno Lossin //! // Get the pin-data type from the initialized type. 221fc6c6baaSBenno Lossin //! // - the function is unsafe, hence the unsafe block 222fc6c6baaSBenno Lossin //! // - we `use` the `HasPinData` trait in the block, it is only available in that 223fc6c6baaSBenno Lossin //! // scope. 224fc6c6baaSBenno Lossin //! let data = unsafe { 225fc6c6baaSBenno Lossin //! use ::kernel::init::__internal::HasPinData; 226fc6c6baaSBenno Lossin //! Self::__pin_data() 227fc6c6baaSBenno Lossin //! }; 228fc6c6baaSBenno Lossin //! // Use `data` to help with type inference, the closure supplied will have the type 229fc6c6baaSBenno Lossin //! // `FnOnce(*mut Self) -> Result<__InitOk, Infallible>`. 230fc6c6baaSBenno Lossin //! let init = ::kernel::init::__internal::PinData::make_closure::< 231fc6c6baaSBenno Lossin //! _, 232fc6c6baaSBenno Lossin //! __InitOk, 233fc6c6baaSBenno Lossin //! ::core::convert::Infallible, 234fc6c6baaSBenno Lossin //! >(data, move |slot| { 235fc6c6baaSBenno Lossin //! { 236fc6c6baaSBenno Lossin //! // Shadow the structure so it cannot be used to return early. If a user 237fc6c6baaSBenno Lossin //! // tries to write `return Ok(__InitOk)`, then they get a type error, since 238fc6c6baaSBenno Lossin //! // that will refer to this struct instead of the one defined above. 239fc6c6baaSBenno Lossin //! struct __InitOk; 240fc6c6baaSBenno Lossin //! // This is the expansion of `t,`, which is syntactic sugar for `t: t,`. 241*309786c2SBenno Lossin //! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).t), t) }; 242fc6c6baaSBenno Lossin //! // Since initialization could fail later (not in this case, since the error 243*309786c2SBenno Lossin //! // type is `Infallible`) we will need to drop this field if there is an 244*309786c2SBenno Lossin //! // error later. This `DropGuard` will drop the field when it gets dropped 245*309786c2SBenno Lossin //! // and has not yet been forgotten. We make a reference to it, so users 246*309786c2SBenno Lossin //! // cannot `mem::forget` it from the initializer, since the name is the same 247*309786c2SBenno Lossin //! // as the field (including hygiene). 248fc6c6baaSBenno Lossin //! let t = &unsafe { 249*309786c2SBenno Lossin //! ::kernel::init::__internal::DropGuard::new( 250*309786c2SBenno Lossin //! ::core::addr_of_mut!((*slot).t), 251*309786c2SBenno Lossin //! ) 252fc6c6baaSBenno Lossin //! }; 253fc6c6baaSBenno Lossin //! // Expansion of `x: 0,`: 254fc6c6baaSBenno Lossin //! // Since this can be an arbitrary expression we cannot place it inside of 255fc6c6baaSBenno Lossin //! // the `unsafe` block, so we bind it here. 256fc6c6baaSBenno Lossin //! let x = 0; 257*309786c2SBenno Lossin //! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).x), x) }; 258*309786c2SBenno Lossin //! // We again create a `DropGuard`. 259fc6c6baaSBenno Lossin //! let x = &unsafe { 260*309786c2SBenno Lossin //! ::kernel::init::__internal::DropGuard::new( 261*309786c2SBenno Lossin //! ::core::addr_of_mut!((*slot).x), 262*309786c2SBenno Lossin //! ) 263fc6c6baaSBenno Lossin //! }; 264fc6c6baaSBenno Lossin //! 265*309786c2SBenno Lossin //! // Here we use the type checker to ensure that every field has been 266fc6c6baaSBenno Lossin //! // initialized exactly once, since this is `if false` it will never get 267fc6c6baaSBenno Lossin //! // executed, but still type-checked. 268fc6c6baaSBenno Lossin //! // Additionally we abuse `slot` to automatically infer the correct type for 269fc6c6baaSBenno Lossin //! // the struct. This is also another check that every field is accessible 270fc6c6baaSBenno Lossin //! // from this scope. 271fc6c6baaSBenno Lossin //! #[allow(unreachable_code, clippy::diverging_sub_expression)] 272fc6c6baaSBenno Lossin //! if false { 273fc6c6baaSBenno Lossin //! unsafe { 274fc6c6baaSBenno Lossin //! ::core::ptr::write( 275fc6c6baaSBenno Lossin //! slot, 276fc6c6baaSBenno Lossin //! Self { 277fc6c6baaSBenno Lossin //! // We only care about typecheck finding every field here, 278fc6c6baaSBenno Lossin //! // the expression does not matter, just conjure one using 279fc6c6baaSBenno Lossin //! // `panic!()`: 280fc6c6baaSBenno Lossin //! t: ::core::panic!(), 281fc6c6baaSBenno Lossin //! x: ::core::panic!(), 282fc6c6baaSBenno Lossin //! }, 283fc6c6baaSBenno Lossin //! ); 284fc6c6baaSBenno Lossin //! }; 285fc6c6baaSBenno Lossin //! } 286fc6c6baaSBenno Lossin //! // Since initialization has successfully completed, we can now forget the 287*309786c2SBenno Lossin //! // guards. This is not `mem::forget`, since we only have `&DropGuard`. 288fc6c6baaSBenno Lossin //! unsafe { ::kernel::init::__internal::DropGuard::forget(t) }; 289fc6c6baaSBenno Lossin //! unsafe { ::kernel::init::__internal::DropGuard::forget(x) }; 290fc6c6baaSBenno Lossin //! } 291fc6c6baaSBenno Lossin //! // We leave the scope above and gain access to the previously shadowed 292fc6c6baaSBenno Lossin //! // `__InitOk` that we need to return. 293fc6c6baaSBenno Lossin //! Ok(__InitOk) 294fc6c6baaSBenno Lossin //! }); 295*309786c2SBenno Lossin //! // Change the return type from `__InitOk` to `()`. 296fc6c6baaSBenno Lossin //! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { 297fc6c6baaSBenno Lossin //! init(slot).map(|__InitOk| ()) 298fc6c6baaSBenno Lossin //! }; 299fc6c6baaSBenno Lossin //! // Construct the initializer. 300fc6c6baaSBenno Lossin //! let init = unsafe { 301fc6c6baaSBenno Lossin //! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init) 302fc6c6baaSBenno Lossin //! }; 303fc6c6baaSBenno Lossin //! init 304fc6c6baaSBenno Lossin //! } 305fc6c6baaSBenno Lossin //! } 306fc6c6baaSBenno Lossin //! } 307fc6c6baaSBenno Lossin //! ``` 308d0fdc396SBenno Lossin //! 309d0fdc396SBenno Lossin //! ## `#[pin_data]` on `Foo` 310d0fdc396SBenno Lossin //! 311d0fdc396SBenno Lossin //! Since we already took a look at `#[pin_data]` on `Bar`, this section will only explain the 312d0fdc396SBenno Lossin //! differences/new things in the expansion of the `Foo` definition: 313d0fdc396SBenno Lossin //! 314*309786c2SBenno Lossin //! ```rust,ignore 315d0fdc396SBenno Lossin //! #[pin_data(PinnedDrop)] 316d0fdc396SBenno Lossin //! struct Foo { 317d0fdc396SBenno Lossin //! a: usize, 318d0fdc396SBenno Lossin //! #[pin] 319d0fdc396SBenno Lossin //! b: Bar<u32>, 320d0fdc396SBenno Lossin //! } 321d0fdc396SBenno Lossin //! ``` 322d0fdc396SBenno Lossin //! 323d0fdc396SBenno Lossin //! This expands to the following code: 324d0fdc396SBenno Lossin //! 325*309786c2SBenno Lossin //! ```rust,ignore 326d0fdc396SBenno Lossin //! struct Foo { 327d0fdc396SBenno Lossin //! a: usize, 328d0fdc396SBenno Lossin //! b: Bar<u32>, 329d0fdc396SBenno Lossin //! } 330d0fdc396SBenno Lossin //! const _: () = { 331d0fdc396SBenno Lossin //! struct __ThePinData { 332d0fdc396SBenno Lossin //! __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>, 333d0fdc396SBenno Lossin //! } 334d0fdc396SBenno Lossin //! impl ::core::clone::Clone for __ThePinData { 335d0fdc396SBenno Lossin //! fn clone(&self) -> Self { 336d0fdc396SBenno Lossin //! *self 337d0fdc396SBenno Lossin //! } 338d0fdc396SBenno Lossin //! } 339d0fdc396SBenno Lossin //! impl ::core::marker::Copy for __ThePinData {} 340d0fdc396SBenno Lossin //! #[allow(dead_code)] 341d0fdc396SBenno Lossin //! impl __ThePinData { 342d0fdc396SBenno Lossin //! unsafe fn b<E>( 343d0fdc396SBenno Lossin //! self, 344d0fdc396SBenno Lossin //! slot: *mut Bar<u32>, 345d0fdc396SBenno Lossin //! init: impl ::kernel::init::PinInit<Bar<u32>, E>, 346d0fdc396SBenno Lossin //! ) -> ::core::result::Result<(), E> { 347d0fdc396SBenno Lossin //! unsafe { ::kernel::init::PinInit::__pinned_init(init, slot) } 348d0fdc396SBenno Lossin //! } 349d0fdc396SBenno Lossin //! unsafe fn a<E>( 350d0fdc396SBenno Lossin //! self, 351d0fdc396SBenno Lossin //! slot: *mut usize, 352d0fdc396SBenno Lossin //! init: impl ::kernel::init::Init<usize, E>, 353d0fdc396SBenno Lossin //! ) -> ::core::result::Result<(), E> { 354d0fdc396SBenno Lossin //! unsafe { ::kernel::init::Init::__init(init, slot) } 355d0fdc396SBenno Lossin //! } 356d0fdc396SBenno Lossin //! } 357d0fdc396SBenno Lossin //! unsafe impl ::kernel::init::__internal::HasPinData for Foo { 358d0fdc396SBenno Lossin //! type PinData = __ThePinData; 359d0fdc396SBenno Lossin //! unsafe fn __pin_data() -> Self::PinData { 360d0fdc396SBenno Lossin //! __ThePinData { 361d0fdc396SBenno Lossin //! __phantom: ::core::marker::PhantomData, 362d0fdc396SBenno Lossin //! } 363d0fdc396SBenno Lossin //! } 364d0fdc396SBenno Lossin //! } 365d0fdc396SBenno Lossin //! unsafe impl ::kernel::init::__internal::PinData for __ThePinData { 366d0fdc396SBenno Lossin //! type Datee = Foo; 367d0fdc396SBenno Lossin //! } 368d0fdc396SBenno Lossin //! #[allow(dead_code)] 369d0fdc396SBenno Lossin //! struct __Unpin<'__pin> { 370d0fdc396SBenno Lossin //! __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>, 371d0fdc396SBenno Lossin //! __phantom: ::core::marker::PhantomData<fn(Foo) -> Foo>, 372d0fdc396SBenno Lossin //! b: Bar<u32>, 373d0fdc396SBenno Lossin //! } 374d0fdc396SBenno Lossin //! #[doc(hidden)] 375d0fdc396SBenno Lossin //! impl<'__pin> ::core::marker::Unpin for Foo where __Unpin<'__pin>: ::core::marker::Unpin {} 376d0fdc396SBenno Lossin //! // Since we specified `PinnedDrop` as the argument to `#[pin_data]`, we expect `Foo` to 377d0fdc396SBenno Lossin //! // implement `PinnedDrop`. Thus we do not need to prevent `Drop` implementations like 378*309786c2SBenno Lossin //! // before, instead we implement `Drop` here and delegate to `PinnedDrop`. 379d0fdc396SBenno Lossin //! impl ::core::ops::Drop for Foo { 380d0fdc396SBenno Lossin //! fn drop(&mut self) { 381d0fdc396SBenno Lossin //! // Since we are getting dropped, no one else has a reference to `self` and thus we 382d0fdc396SBenno Lossin //! // can assume that we never move. 383d0fdc396SBenno Lossin //! let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) }; 384d0fdc396SBenno Lossin //! // Create the unsafe token that proves that we are inside of a destructor, this 385d0fdc396SBenno Lossin //! // type is only allowed to be created in a destructor. 386d0fdc396SBenno Lossin //! let token = unsafe { ::kernel::init::__internal::OnlyCallFromDrop::new() }; 387d0fdc396SBenno Lossin //! ::kernel::init::PinnedDrop::drop(pinned, token); 388d0fdc396SBenno Lossin //! } 389d0fdc396SBenno Lossin //! } 390d0fdc396SBenno Lossin //! }; 391d0fdc396SBenno Lossin //! ``` 392d0fdc396SBenno Lossin //! 393d0fdc396SBenno Lossin //! ## `#[pinned_drop]` on `impl PinnedDrop for Foo` 394d0fdc396SBenno Lossin //! 395d0fdc396SBenno Lossin //! This macro is used to implement the `PinnedDrop` trait, since that trait is `unsafe` and has an 396d0fdc396SBenno Lossin //! extra parameter that should not be used at all. The macro hides that parameter. 397d0fdc396SBenno Lossin //! 398d0fdc396SBenno Lossin //! Here is the `PinnedDrop` impl for `Foo`: 399d0fdc396SBenno Lossin //! 400*309786c2SBenno Lossin //! ```rust,ignore 401d0fdc396SBenno Lossin //! #[pinned_drop] 402d0fdc396SBenno Lossin //! impl PinnedDrop for Foo { 403d0fdc396SBenno Lossin //! fn drop(self: Pin<&mut Self>) { 404d0fdc396SBenno Lossin //! println!("{self:p} is getting dropped."); 405d0fdc396SBenno Lossin //! } 406d0fdc396SBenno Lossin //! } 407d0fdc396SBenno Lossin //! ``` 408d0fdc396SBenno Lossin //! 409d0fdc396SBenno Lossin //! This expands to the following code: 410d0fdc396SBenno Lossin //! 411*309786c2SBenno Lossin //! ```rust,ignore 412d0fdc396SBenno Lossin //! // `unsafe`, full path and the token parameter are added, everything else stays the same. 413d0fdc396SBenno Lossin //! unsafe impl ::kernel::init::PinnedDrop for Foo { 414d0fdc396SBenno Lossin //! fn drop(self: Pin<&mut Self>, _: ::kernel::init::__internal::OnlyCallFromDrop) { 415d0fdc396SBenno Lossin //! println!("{self:p} is getting dropped."); 416d0fdc396SBenno Lossin //! } 417d0fdc396SBenno Lossin //! } 418d0fdc396SBenno Lossin //! ``` 419d0fdc396SBenno Lossin //! 420d0fdc396SBenno Lossin //! ## `pin_init!` on `Foo` 421d0fdc396SBenno Lossin //! 422*309786c2SBenno Lossin //! Since we already took a look at `pin_init!` on `Bar`, this section will only show the expansion 423*309786c2SBenno Lossin //! of `pin_init!` on `Foo`: 424d0fdc396SBenno Lossin //! 425*309786c2SBenno Lossin //! ```rust,ignore 426d0fdc396SBenno Lossin //! let a = 42; 427d0fdc396SBenno Lossin //! let initializer = pin_init!(Foo { 428d0fdc396SBenno Lossin //! a, 429d0fdc396SBenno Lossin //! b <- Bar::new(36), 430d0fdc396SBenno Lossin //! }); 431d0fdc396SBenno Lossin //! ``` 432d0fdc396SBenno Lossin //! 433d0fdc396SBenno Lossin //! This expands to the following code: 434d0fdc396SBenno Lossin //! 435*309786c2SBenno Lossin //! ```rust,ignore 436d0fdc396SBenno Lossin //! let a = 42; 437d0fdc396SBenno Lossin //! let initializer = { 438d0fdc396SBenno Lossin //! struct __InitOk; 439d0fdc396SBenno Lossin //! let data = unsafe { 440d0fdc396SBenno Lossin //! use ::kernel::init::__internal::HasPinData; 441d0fdc396SBenno Lossin //! Foo::__pin_data() 442d0fdc396SBenno Lossin //! }; 443d0fdc396SBenno Lossin //! let init = ::kernel::init::__internal::PinData::make_closure::< 444d0fdc396SBenno Lossin //! _, 445d0fdc396SBenno Lossin //! __InitOk, 446d0fdc396SBenno Lossin //! ::core::convert::Infallible, 447d0fdc396SBenno Lossin //! >(data, move |slot| { 448d0fdc396SBenno Lossin //! { 449d0fdc396SBenno Lossin //! struct __InitOk; 450*309786c2SBenno Lossin //! unsafe { ::core::ptr::write(::core::addr_of_mut!((*slot).a), a) }; 451*309786c2SBenno Lossin //! let a = &unsafe { 452*309786c2SBenno Lossin //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).a)) 453*309786c2SBenno Lossin //! }; 454d0fdc396SBenno Lossin //! let b = Bar::new(36); 455*309786c2SBenno Lossin //! unsafe { data.b(::core::addr_of_mut!((*slot).b), b)? }; 456*309786c2SBenno Lossin //! let b = &unsafe { 457*309786c2SBenno Lossin //! ::kernel::init::__internal::DropGuard::new(::core::addr_of_mut!((*slot).b)) 458*309786c2SBenno Lossin //! }; 459d0fdc396SBenno Lossin //! 460d0fdc396SBenno Lossin //! #[allow(unreachable_code, clippy::diverging_sub_expression)] 461d0fdc396SBenno Lossin //! if false { 462d0fdc396SBenno Lossin //! unsafe { 463d0fdc396SBenno Lossin //! ::core::ptr::write( 464d0fdc396SBenno Lossin //! slot, 465d0fdc396SBenno Lossin //! Foo { 466d0fdc396SBenno Lossin //! a: ::core::panic!(), 467d0fdc396SBenno Lossin //! b: ::core::panic!(), 468d0fdc396SBenno Lossin //! }, 469d0fdc396SBenno Lossin //! ); 470d0fdc396SBenno Lossin //! }; 471d0fdc396SBenno Lossin //! } 472d0fdc396SBenno Lossin //! unsafe { ::kernel::init::__internal::DropGuard::forget(a) }; 473d0fdc396SBenno Lossin //! unsafe { ::kernel::init::__internal::DropGuard::forget(b) }; 474d0fdc396SBenno Lossin //! } 475d0fdc396SBenno Lossin //! Ok(__InitOk) 476d0fdc396SBenno Lossin //! }); 477d0fdc396SBenno Lossin //! let init = move |slot| -> ::core::result::Result<(), ::core::convert::Infallible> { 478d0fdc396SBenno Lossin //! init(slot).map(|__InitOk| ()) 479d0fdc396SBenno Lossin //! }; 480d0fdc396SBenno Lossin //! let init = unsafe { 481d0fdc396SBenno Lossin //! ::kernel::init::pin_init_from_closure::<_, ::core::convert::Infallible>(init) 482d0fdc396SBenno Lossin //! }; 483d0fdc396SBenno Lossin //! init 484d0fdc396SBenno Lossin //! }; 485d0fdc396SBenno Lossin //! ``` 486d0fdc396SBenno Lossin 487d0fdc396SBenno Lossin /// Creates a `unsafe impl<...> PinnedDrop for $type` block. 488d0fdc396SBenno Lossin /// 489d0fdc396SBenno Lossin /// See [`PinnedDrop`] for more information. 490d0fdc396SBenno Lossin #[doc(hidden)] 491d0fdc396SBenno Lossin #[macro_export] 492d0fdc396SBenno Lossin macro_rules! __pinned_drop { 493d0fdc396SBenno Lossin ( 494d0fdc396SBenno Lossin @impl_sig($($impl_sig:tt)*), 495d0fdc396SBenno Lossin @impl_body( 496d0fdc396SBenno Lossin $(#[$($attr:tt)*])* 497d0fdc396SBenno Lossin fn drop($($sig:tt)*) { 498d0fdc396SBenno Lossin $($inner:tt)* 499d0fdc396SBenno Lossin } 500d0fdc396SBenno Lossin ), 501d0fdc396SBenno Lossin ) => { 502d0fdc396SBenno Lossin unsafe $($impl_sig)* { 503d0fdc396SBenno Lossin // Inherit all attributes and the type/ident tokens for the signature. 504d0fdc396SBenno Lossin $(#[$($attr)*])* 505d0fdc396SBenno Lossin fn drop($($sig)*, _: $crate::init::__internal::OnlyCallFromDrop) { 506d0fdc396SBenno Lossin $($inner)* 507d0fdc396SBenno Lossin } 508d0fdc396SBenno Lossin } 509d0fdc396SBenno Lossin } 510d0fdc396SBenno Lossin } 511fc6c6baaSBenno Lossin 512fc6c6baaSBenno Lossin /// This macro first parses the struct definition such that it separates pinned and not pinned 513fc6c6baaSBenno Lossin /// fields. Afterwards it declares the struct and implement the `PinData` trait safely. 514fc6c6baaSBenno Lossin #[doc(hidden)] 515fc6c6baaSBenno Lossin #[macro_export] 516fc6c6baaSBenno Lossin macro_rules! __pin_data { 517fc6c6baaSBenno Lossin // Proc-macro entry point, this is supplied by the proc-macro pre-parsing. 518fc6c6baaSBenno Lossin (parse_input: 519fc6c6baaSBenno Lossin @args($($pinned_drop:ident)?), 520fc6c6baaSBenno Lossin @sig( 521fc6c6baaSBenno Lossin $(#[$($struct_attr:tt)*])* 522fc6c6baaSBenno Lossin $vis:vis struct $name:ident 523fc6c6baaSBenno Lossin $(where $($whr:tt)*)? 524fc6c6baaSBenno Lossin ), 525fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 526fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 527fc6c6baaSBenno Lossin @body({ $($fields:tt)* }), 528fc6c6baaSBenno Lossin ) => { 529fc6c6baaSBenno Lossin // We now use token munching to iterate through all of the fields. While doing this we 530fc6c6baaSBenno Lossin // identify fields marked with `#[pin]`, these fields are the 'pinned fields'. The user 531fc6c6baaSBenno Lossin // wants these to be structurally pinned. The rest of the fields are the 532fc6c6baaSBenno Lossin // 'not pinned fields'. Additionally we collect all fields, since we need them in the right 533fc6c6baaSBenno Lossin // order to declare the struct. 534fc6c6baaSBenno Lossin // 535fc6c6baaSBenno Lossin // In this call we also put some explaining comments for the parameters. 536fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 537fc6c6baaSBenno Lossin // Attributes on the struct itself, these will just be propagated to be put onto the 538fc6c6baaSBenno Lossin // struct definition. 539fc6c6baaSBenno Lossin @struct_attrs($(#[$($struct_attr)*])*), 540fc6c6baaSBenno Lossin // The visibility of the struct. 541fc6c6baaSBenno Lossin @vis($vis), 542fc6c6baaSBenno Lossin // The name of the struct. 543fc6c6baaSBenno Lossin @name($name), 544fc6c6baaSBenno Lossin // The 'impl generics', the generics that will need to be specified on the struct inside 545fc6c6baaSBenno Lossin // of an `impl<$ty_generics>` block. 546fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 547fc6c6baaSBenno Lossin // The 'ty generics', the generics that will need to be specified on the impl blocks. 548fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 549fc6c6baaSBenno Lossin // The where clause of any impl block and the declaration. 550fc6c6baaSBenno Lossin @where($($($whr)*)?), 551fc6c6baaSBenno Lossin // The remaining fields tokens that need to be processed. 552fc6c6baaSBenno Lossin // We add a `,` at the end to ensure correct parsing. 553fc6c6baaSBenno Lossin @fields_munch($($fields)* ,), 554fc6c6baaSBenno Lossin // The pinned fields. 555fc6c6baaSBenno Lossin @pinned(), 556fc6c6baaSBenno Lossin // The not pinned fields. 557fc6c6baaSBenno Lossin @not_pinned(), 558fc6c6baaSBenno Lossin // All fields. 559fc6c6baaSBenno Lossin @fields(), 560fc6c6baaSBenno Lossin // The accumulator containing all attributes already parsed. 561fc6c6baaSBenno Lossin @accum(), 562fc6c6baaSBenno Lossin // Contains `yes` or `` to indicate if `#[pin]` was found on the current field. 563fc6c6baaSBenno Lossin @is_pinned(), 564fc6c6baaSBenno Lossin // The proc-macro argument, this should be `PinnedDrop` or ``. 565fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 566fc6c6baaSBenno Lossin ); 567fc6c6baaSBenno Lossin }; 568fc6c6baaSBenno Lossin (find_pinned_fields: 569fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 570fc6c6baaSBenno Lossin @vis($vis:vis), 571fc6c6baaSBenno Lossin @name($name:ident), 572fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 573fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 574fc6c6baaSBenno Lossin @where($($whr:tt)*), 575fc6c6baaSBenno Lossin // We found a PhantomPinned field, this should generally be pinned! 576fc6c6baaSBenno Lossin @fields_munch($field:ident : $($($(::)?core::)?marker::)?PhantomPinned, $($rest:tt)*), 577fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 578fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 579fc6c6baaSBenno Lossin @fields($($fields:tt)*), 580fc6c6baaSBenno Lossin @accum($($accum:tt)*), 581fc6c6baaSBenno Lossin // This field is not pinned. 582fc6c6baaSBenno Lossin @is_pinned(), 583fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 584fc6c6baaSBenno Lossin ) => { 585fc6c6baaSBenno Lossin ::core::compile_error!(concat!( 586fc6c6baaSBenno Lossin "The field `", 587fc6c6baaSBenno Lossin stringify!($field), 588fc6c6baaSBenno Lossin "` of type `PhantomPinned` only has an effect, if it has the `#[pin]` attribute.", 589fc6c6baaSBenno Lossin )); 590fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 591fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs)*), 592fc6c6baaSBenno Lossin @vis($vis), 593fc6c6baaSBenno Lossin @name($name), 594fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 595fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 596fc6c6baaSBenno Lossin @where($($whr)*), 597fc6c6baaSBenno Lossin @fields_munch($($rest)*), 598fc6c6baaSBenno Lossin @pinned($($pinned)* $($accum)* $field: ::core::marker::PhantomPinned,), 599fc6c6baaSBenno Lossin @not_pinned($($not_pinned)*), 600fc6c6baaSBenno Lossin @fields($($fields)* $($accum)* $field: ::core::marker::PhantomPinned,), 601fc6c6baaSBenno Lossin @accum(), 602fc6c6baaSBenno Lossin @is_pinned(), 603fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 604fc6c6baaSBenno Lossin ); 605fc6c6baaSBenno Lossin }; 606fc6c6baaSBenno Lossin (find_pinned_fields: 607fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 608fc6c6baaSBenno Lossin @vis($vis:vis), 609fc6c6baaSBenno Lossin @name($name:ident), 610fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 611fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 612fc6c6baaSBenno Lossin @where($($whr:tt)*), 613fc6c6baaSBenno Lossin // We reached the field declaration. 614fc6c6baaSBenno Lossin @fields_munch($field:ident : $type:ty, $($rest:tt)*), 615fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 616fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 617fc6c6baaSBenno Lossin @fields($($fields:tt)*), 618fc6c6baaSBenno Lossin @accum($($accum:tt)*), 619fc6c6baaSBenno Lossin // This field is pinned. 620fc6c6baaSBenno Lossin @is_pinned(yes), 621fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 622fc6c6baaSBenno Lossin ) => { 623fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 624fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs)*), 625fc6c6baaSBenno Lossin @vis($vis), 626fc6c6baaSBenno Lossin @name($name), 627fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 628fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 629fc6c6baaSBenno Lossin @where($($whr)*), 630fc6c6baaSBenno Lossin @fields_munch($($rest)*), 631fc6c6baaSBenno Lossin @pinned($($pinned)* $($accum)* $field: $type,), 632fc6c6baaSBenno Lossin @not_pinned($($not_pinned)*), 633fc6c6baaSBenno Lossin @fields($($fields)* $($accum)* $field: $type,), 634fc6c6baaSBenno Lossin @accum(), 635fc6c6baaSBenno Lossin @is_pinned(), 636fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 637fc6c6baaSBenno Lossin ); 638fc6c6baaSBenno Lossin }; 639fc6c6baaSBenno Lossin (find_pinned_fields: 640fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 641fc6c6baaSBenno Lossin @vis($vis:vis), 642fc6c6baaSBenno Lossin @name($name:ident), 643fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 644fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 645fc6c6baaSBenno Lossin @where($($whr:tt)*), 646fc6c6baaSBenno Lossin // We reached the field declaration. 647fc6c6baaSBenno Lossin @fields_munch($field:ident : $type:ty, $($rest:tt)*), 648fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 649fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 650fc6c6baaSBenno Lossin @fields($($fields:tt)*), 651fc6c6baaSBenno Lossin @accum($($accum:tt)*), 652fc6c6baaSBenno Lossin // This field is not pinned. 653fc6c6baaSBenno Lossin @is_pinned(), 654fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 655fc6c6baaSBenno Lossin ) => { 656fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 657fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs)*), 658fc6c6baaSBenno Lossin @vis($vis), 659fc6c6baaSBenno Lossin @name($name), 660fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 661fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 662fc6c6baaSBenno Lossin @where($($whr)*), 663fc6c6baaSBenno Lossin @fields_munch($($rest)*), 664fc6c6baaSBenno Lossin @pinned($($pinned)*), 665fc6c6baaSBenno Lossin @not_pinned($($not_pinned)* $($accum)* $field: $type,), 666fc6c6baaSBenno Lossin @fields($($fields)* $($accum)* $field: $type,), 667fc6c6baaSBenno Lossin @accum(), 668fc6c6baaSBenno Lossin @is_pinned(), 669fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 670fc6c6baaSBenno Lossin ); 671fc6c6baaSBenno Lossin }; 672fc6c6baaSBenno Lossin (find_pinned_fields: 673fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 674fc6c6baaSBenno Lossin @vis($vis:vis), 675fc6c6baaSBenno Lossin @name($name:ident), 676fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 677fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 678fc6c6baaSBenno Lossin @where($($whr:tt)*), 679fc6c6baaSBenno Lossin // We found the `#[pin]` attr. 680fc6c6baaSBenno Lossin @fields_munch(#[pin] $($rest:tt)*), 681fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 682fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 683fc6c6baaSBenno Lossin @fields($($fields:tt)*), 684fc6c6baaSBenno Lossin @accum($($accum:tt)*), 685fc6c6baaSBenno Lossin @is_pinned($($is_pinned:ident)?), 686fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 687fc6c6baaSBenno Lossin ) => { 688fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 689fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs)*), 690fc6c6baaSBenno Lossin @vis($vis), 691fc6c6baaSBenno Lossin @name($name), 692fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 693fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 694fc6c6baaSBenno Lossin @where($($whr)*), 695fc6c6baaSBenno Lossin @fields_munch($($rest)*), 696fc6c6baaSBenno Lossin // We do not include `#[pin]` in the list of attributes, since it is not actually an 697fc6c6baaSBenno Lossin // attribute that is defined somewhere. 698fc6c6baaSBenno Lossin @pinned($($pinned)*), 699fc6c6baaSBenno Lossin @not_pinned($($not_pinned)*), 700fc6c6baaSBenno Lossin @fields($($fields)*), 701fc6c6baaSBenno Lossin @accum($($accum)*), 702fc6c6baaSBenno Lossin // Set this to `yes`. 703fc6c6baaSBenno Lossin @is_pinned(yes), 704fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 705fc6c6baaSBenno Lossin ); 706fc6c6baaSBenno Lossin }; 707fc6c6baaSBenno Lossin (find_pinned_fields: 708fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 709fc6c6baaSBenno Lossin @vis($vis:vis), 710fc6c6baaSBenno Lossin @name($name:ident), 711fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 712fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 713fc6c6baaSBenno Lossin @where($($whr:tt)*), 714fc6c6baaSBenno Lossin // We reached the field declaration with visibility, for simplicity we only munch the 715fc6c6baaSBenno Lossin // visibility and put it into `$accum`. 716fc6c6baaSBenno Lossin @fields_munch($fvis:vis $field:ident $($rest:tt)*), 717fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 718fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 719fc6c6baaSBenno Lossin @fields($($fields:tt)*), 720fc6c6baaSBenno Lossin @accum($($accum:tt)*), 721fc6c6baaSBenno Lossin @is_pinned($($is_pinned:ident)?), 722fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 723fc6c6baaSBenno Lossin ) => { 724fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 725fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs)*), 726fc6c6baaSBenno Lossin @vis($vis), 727fc6c6baaSBenno Lossin @name($name), 728fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 729fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 730fc6c6baaSBenno Lossin @where($($whr)*), 731fc6c6baaSBenno Lossin @fields_munch($field $($rest)*), 732fc6c6baaSBenno Lossin @pinned($($pinned)*), 733fc6c6baaSBenno Lossin @not_pinned($($not_pinned)*), 734fc6c6baaSBenno Lossin @fields($($fields)*), 735fc6c6baaSBenno Lossin @accum($($accum)* $fvis), 736fc6c6baaSBenno Lossin @is_pinned($($is_pinned)?), 737fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 738fc6c6baaSBenno Lossin ); 739fc6c6baaSBenno Lossin }; 740fc6c6baaSBenno Lossin (find_pinned_fields: 741fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 742fc6c6baaSBenno Lossin @vis($vis:vis), 743fc6c6baaSBenno Lossin @name($name:ident), 744fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 745fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 746fc6c6baaSBenno Lossin @where($($whr:tt)*), 747fc6c6baaSBenno Lossin // Some other attribute, just put it into `$accum`. 748fc6c6baaSBenno Lossin @fields_munch(#[$($attr:tt)*] $($rest:tt)*), 749fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 750fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 751fc6c6baaSBenno Lossin @fields($($fields:tt)*), 752fc6c6baaSBenno Lossin @accum($($accum:tt)*), 753fc6c6baaSBenno Lossin @is_pinned($($is_pinned:ident)?), 754fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 755fc6c6baaSBenno Lossin ) => { 756fc6c6baaSBenno Lossin $crate::__pin_data!(find_pinned_fields: 757fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs)*), 758fc6c6baaSBenno Lossin @vis($vis), 759fc6c6baaSBenno Lossin @name($name), 760fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 761fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 762fc6c6baaSBenno Lossin @where($($whr)*), 763fc6c6baaSBenno Lossin @fields_munch($($rest)*), 764fc6c6baaSBenno Lossin @pinned($($pinned)*), 765fc6c6baaSBenno Lossin @not_pinned($($not_pinned)*), 766fc6c6baaSBenno Lossin @fields($($fields)*), 767fc6c6baaSBenno Lossin @accum($($accum)* #[$($attr)*]), 768fc6c6baaSBenno Lossin @is_pinned($($is_pinned)?), 769fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 770fc6c6baaSBenno Lossin ); 771fc6c6baaSBenno Lossin }; 772fc6c6baaSBenno Lossin (find_pinned_fields: 773fc6c6baaSBenno Lossin @struct_attrs($($struct_attrs:tt)*), 774fc6c6baaSBenno Lossin @vis($vis:vis), 775fc6c6baaSBenno Lossin @name($name:ident), 776fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 777fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 778fc6c6baaSBenno Lossin @where($($whr:tt)*), 779fc6c6baaSBenno Lossin // We reached the end of the fields, plus an optional additional comma, since we added one 780fc6c6baaSBenno Lossin // before and the user is also allowed to put a trailing comma. 781fc6c6baaSBenno Lossin @fields_munch($(,)?), 782fc6c6baaSBenno Lossin @pinned($($pinned:tt)*), 783fc6c6baaSBenno Lossin @not_pinned($($not_pinned:tt)*), 784fc6c6baaSBenno Lossin @fields($($fields:tt)*), 785fc6c6baaSBenno Lossin @accum(), 786fc6c6baaSBenno Lossin @is_pinned(), 787fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop:ident)?), 788fc6c6baaSBenno Lossin ) => { 789fc6c6baaSBenno Lossin // Declare the struct with all fields in the correct order. 790fc6c6baaSBenno Lossin $($struct_attrs)* 791fc6c6baaSBenno Lossin $vis struct $name <$($impl_generics)*> 792fc6c6baaSBenno Lossin where $($whr)* 793fc6c6baaSBenno Lossin { 794fc6c6baaSBenno Lossin $($fields)* 795fc6c6baaSBenno Lossin } 796fc6c6baaSBenno Lossin 797fc6c6baaSBenno Lossin // We put the rest into this const item, because it then will not be accessible to anything 798fc6c6baaSBenno Lossin // outside. 799fc6c6baaSBenno Lossin const _: () = { 800fc6c6baaSBenno Lossin // We declare this struct which will host all of the projection function for our type. 801fc6c6baaSBenno Lossin // it will be invariant over all generic parameters which are inherited from the 802fc6c6baaSBenno Lossin // struct. 803fc6c6baaSBenno Lossin $vis struct __ThePinData<$($impl_generics)*> 804fc6c6baaSBenno Lossin where $($whr)* 805fc6c6baaSBenno Lossin { 806fc6c6baaSBenno Lossin __phantom: ::core::marker::PhantomData< 807fc6c6baaSBenno Lossin fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*> 808fc6c6baaSBenno Lossin >, 809fc6c6baaSBenno Lossin } 810fc6c6baaSBenno Lossin 811fc6c6baaSBenno Lossin impl<$($impl_generics)*> ::core::clone::Clone for __ThePinData<$($ty_generics)*> 812fc6c6baaSBenno Lossin where $($whr)* 813fc6c6baaSBenno Lossin { 814fc6c6baaSBenno Lossin fn clone(&self) -> Self { *self } 815fc6c6baaSBenno Lossin } 816fc6c6baaSBenno Lossin 817fc6c6baaSBenno Lossin impl<$($impl_generics)*> ::core::marker::Copy for __ThePinData<$($ty_generics)*> 818fc6c6baaSBenno Lossin where $($whr)* 819fc6c6baaSBenno Lossin {} 820fc6c6baaSBenno Lossin 821fc6c6baaSBenno Lossin // Make all projection functions. 822fc6c6baaSBenno Lossin $crate::__pin_data!(make_pin_data: 823fc6c6baaSBenno Lossin @pin_data(__ThePinData), 824fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 825fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 826fc6c6baaSBenno Lossin @where($($whr)*), 827fc6c6baaSBenno Lossin @pinned($($pinned)*), 828fc6c6baaSBenno Lossin @not_pinned($($not_pinned)*), 829fc6c6baaSBenno Lossin ); 830fc6c6baaSBenno Lossin 831fc6c6baaSBenno Lossin // SAFETY: We have added the correct projection functions above to `__ThePinData` and 832fc6c6baaSBenno Lossin // we also use the least restrictive generics possible. 833fc6c6baaSBenno Lossin unsafe impl<$($impl_generics)*> 834fc6c6baaSBenno Lossin $crate::init::__internal::HasPinData for $name<$($ty_generics)*> 835fc6c6baaSBenno Lossin where $($whr)* 836fc6c6baaSBenno Lossin { 837fc6c6baaSBenno Lossin type PinData = __ThePinData<$($ty_generics)*>; 838fc6c6baaSBenno Lossin 839fc6c6baaSBenno Lossin unsafe fn __pin_data() -> Self::PinData { 840fc6c6baaSBenno Lossin __ThePinData { __phantom: ::core::marker::PhantomData } 841fc6c6baaSBenno Lossin } 842fc6c6baaSBenno Lossin } 843fc6c6baaSBenno Lossin 844fc6c6baaSBenno Lossin unsafe impl<$($impl_generics)*> 845fc6c6baaSBenno Lossin $crate::init::__internal::PinData for __ThePinData<$($ty_generics)*> 846fc6c6baaSBenno Lossin where $($whr)* 847fc6c6baaSBenno Lossin { 848fc6c6baaSBenno Lossin type Datee = $name<$($ty_generics)*>; 849fc6c6baaSBenno Lossin } 850fc6c6baaSBenno Lossin 851fc6c6baaSBenno Lossin // This struct will be used for the unpin analysis. Since only structurally pinned 852fc6c6baaSBenno Lossin // fields are relevant whether the struct should implement `Unpin`. 853fc6c6baaSBenno Lossin #[allow(dead_code)] 854fc6c6baaSBenno Lossin struct __Unpin <'__pin, $($impl_generics)*> 855fc6c6baaSBenno Lossin where $($whr)* 856fc6c6baaSBenno Lossin { 857fc6c6baaSBenno Lossin __phantom_pin: ::core::marker::PhantomData<fn(&'__pin ()) -> &'__pin ()>, 858fc6c6baaSBenno Lossin __phantom: ::core::marker::PhantomData< 859fc6c6baaSBenno Lossin fn($name<$($ty_generics)*>) -> $name<$($ty_generics)*> 860fc6c6baaSBenno Lossin >, 861fc6c6baaSBenno Lossin // Only the pinned fields. 862fc6c6baaSBenno Lossin $($pinned)* 863fc6c6baaSBenno Lossin } 864fc6c6baaSBenno Lossin 865fc6c6baaSBenno Lossin #[doc(hidden)] 866fc6c6baaSBenno Lossin impl<'__pin, $($impl_generics)*> ::core::marker::Unpin for $name<$($ty_generics)*> 867fc6c6baaSBenno Lossin where 868fc6c6baaSBenno Lossin __Unpin<'__pin, $($ty_generics)*>: ::core::marker::Unpin, 869fc6c6baaSBenno Lossin $($whr)* 870fc6c6baaSBenno Lossin {} 871fc6c6baaSBenno Lossin 872fc6c6baaSBenno Lossin // We need to disallow normal `Drop` implementation, the exact behavior depends on 873fc6c6baaSBenno Lossin // whether `PinnedDrop` was specified as the parameter. 874fc6c6baaSBenno Lossin $crate::__pin_data!(drop_prevention: 875fc6c6baaSBenno Lossin @name($name), 876fc6c6baaSBenno Lossin @impl_generics($($impl_generics)*), 877fc6c6baaSBenno Lossin @ty_generics($($ty_generics)*), 878fc6c6baaSBenno Lossin @where($($whr)*), 879fc6c6baaSBenno Lossin @pinned_drop($($pinned_drop)?), 880fc6c6baaSBenno Lossin ); 881fc6c6baaSBenno Lossin }; 882fc6c6baaSBenno Lossin }; 883fc6c6baaSBenno Lossin // When no `PinnedDrop` was specified, then we have to prevent implementing drop. 884fc6c6baaSBenno Lossin (drop_prevention: 885fc6c6baaSBenno Lossin @name($name:ident), 886fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 887fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 888fc6c6baaSBenno Lossin @where($($whr:tt)*), 889fc6c6baaSBenno Lossin @pinned_drop(), 890fc6c6baaSBenno Lossin ) => { 891fc6c6baaSBenno Lossin // We prevent this by creating a trait that will be implemented for all types implementing 892fc6c6baaSBenno Lossin // `Drop`. Additionally we will implement this trait for the struct leading to a conflict, 893fc6c6baaSBenno Lossin // if it also implements `Drop` 894fc6c6baaSBenno Lossin trait MustNotImplDrop {} 895fc6c6baaSBenno Lossin #[allow(drop_bounds)] 896fc6c6baaSBenno Lossin impl<T: ::core::ops::Drop> MustNotImplDrop for T {} 897fc6c6baaSBenno Lossin impl<$($impl_generics)*> MustNotImplDrop for $name<$($ty_generics)*> 898fc6c6baaSBenno Lossin where $($whr)* {} 899d0fdc396SBenno Lossin // We also take care to prevent users from writing a useless `PinnedDrop` implementation. 900d0fdc396SBenno Lossin // They might implement `PinnedDrop` correctly for the struct, but forget to give 901d0fdc396SBenno Lossin // `PinnedDrop` as the parameter to `#[pin_data]`. 902d0fdc396SBenno Lossin #[allow(non_camel_case_types)] 903d0fdc396SBenno Lossin trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {} 904d0fdc396SBenno Lossin impl<T: $crate::init::PinnedDrop> 905d0fdc396SBenno Lossin UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} 906d0fdc396SBenno Lossin impl<$($impl_generics)*> 907d0fdc396SBenno Lossin UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for $name<$($ty_generics)*> 908d0fdc396SBenno Lossin where $($whr)* {} 909d0fdc396SBenno Lossin }; 910d0fdc396SBenno Lossin // When `PinnedDrop` was specified we just implement `Drop` and delegate. 911d0fdc396SBenno Lossin (drop_prevention: 912d0fdc396SBenno Lossin @name($name:ident), 913d0fdc396SBenno Lossin @impl_generics($($impl_generics:tt)*), 914d0fdc396SBenno Lossin @ty_generics($($ty_generics:tt)*), 915d0fdc396SBenno Lossin @where($($whr:tt)*), 916d0fdc396SBenno Lossin @pinned_drop(PinnedDrop), 917d0fdc396SBenno Lossin ) => { 918d0fdc396SBenno Lossin impl<$($impl_generics)*> ::core::ops::Drop for $name<$($ty_generics)*> 919d0fdc396SBenno Lossin where $($whr)* 920d0fdc396SBenno Lossin { 921d0fdc396SBenno Lossin fn drop(&mut self) { 922d0fdc396SBenno Lossin // SAFETY: Since this is a destructor, `self` will not move after this function 923d0fdc396SBenno Lossin // terminates, since it is inaccessible. 924d0fdc396SBenno Lossin let pinned = unsafe { ::core::pin::Pin::new_unchecked(self) }; 925d0fdc396SBenno Lossin // SAFETY: Since this is a drop function, we can create this token to call the 926d0fdc396SBenno Lossin // pinned destructor of this type. 927d0fdc396SBenno Lossin let token = unsafe { $crate::init::__internal::OnlyCallFromDrop::new() }; 928d0fdc396SBenno Lossin $crate::init::PinnedDrop::drop(pinned, token); 929d0fdc396SBenno Lossin } 930d0fdc396SBenno Lossin } 931fc6c6baaSBenno Lossin }; 932fc6c6baaSBenno Lossin // If some other parameter was specified, we emit a readable error. 933fc6c6baaSBenno Lossin (drop_prevention: 934fc6c6baaSBenno Lossin @name($name:ident), 935fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 936fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 937fc6c6baaSBenno Lossin @where($($whr:tt)*), 938fc6c6baaSBenno Lossin @pinned_drop($($rest:tt)*), 939fc6c6baaSBenno Lossin ) => { 940fc6c6baaSBenno Lossin compile_error!( 941fc6c6baaSBenno Lossin "Wrong parameters to `#[pin_data]`, expected nothing or `PinnedDrop`, got '{}'.", 942fc6c6baaSBenno Lossin stringify!($($rest)*), 943fc6c6baaSBenno Lossin ); 944fc6c6baaSBenno Lossin }; 945fc6c6baaSBenno Lossin (make_pin_data: 946fc6c6baaSBenno Lossin @pin_data($pin_data:ident), 947fc6c6baaSBenno Lossin @impl_generics($($impl_generics:tt)*), 948fc6c6baaSBenno Lossin @ty_generics($($ty_generics:tt)*), 949fc6c6baaSBenno Lossin @where($($whr:tt)*), 950fc6c6baaSBenno Lossin @pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?), 951fc6c6baaSBenno Lossin @not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?), 952fc6c6baaSBenno Lossin ) => { 953fc6c6baaSBenno Lossin // For every field, we create a projection function according to its projection type. If a 954fc6c6baaSBenno Lossin // field is structurally pinned, then it must be initialized via `PinInit`, if it is not 955fc6c6baaSBenno Lossin // structurally pinned, then it can be initialized via `Init`. 956fc6c6baaSBenno Lossin // 957fc6c6baaSBenno Lossin // The functions are `unsafe` to prevent accidentally calling them. 958fc6c6baaSBenno Lossin #[allow(dead_code)] 959fc6c6baaSBenno Lossin impl<$($impl_generics)*> $pin_data<$($ty_generics)*> 960fc6c6baaSBenno Lossin where $($whr)* 961fc6c6baaSBenno Lossin { 962fc6c6baaSBenno Lossin $( 963fc6c6baaSBenno Lossin $pvis unsafe fn $p_field<E>( 964fc6c6baaSBenno Lossin self, 965fc6c6baaSBenno Lossin slot: *mut $p_type, 966fc6c6baaSBenno Lossin init: impl $crate::init::PinInit<$p_type, E>, 967fc6c6baaSBenno Lossin ) -> ::core::result::Result<(), E> { 968fc6c6baaSBenno Lossin unsafe { $crate::init::PinInit::__pinned_init(init, slot) } 969fc6c6baaSBenno Lossin } 970fc6c6baaSBenno Lossin )* 971fc6c6baaSBenno Lossin $( 972fc6c6baaSBenno Lossin $fvis unsafe fn $field<E>( 973fc6c6baaSBenno Lossin self, 974fc6c6baaSBenno Lossin slot: *mut $type, 975fc6c6baaSBenno Lossin init: impl $crate::init::Init<$type, E>, 976fc6c6baaSBenno Lossin ) -> ::core::result::Result<(), E> { 977fc6c6baaSBenno Lossin unsafe { $crate::init::Init::__init(init, slot) } 978fc6c6baaSBenno Lossin } 979fc6c6baaSBenno Lossin )* 980fc6c6baaSBenno Lossin } 981fc6c6baaSBenno Lossin }; 982fc6c6baaSBenno Lossin } 983