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