1*4883830eSBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT 2*4883830eSBenno Lossin 3*4883830eSBenno Lossin use proc_macro2::{Span, TokenStream}; 4*4883830eSBenno Lossin use quote::{format_ident, quote, quote_spanned}; 5*4883830eSBenno Lossin use syn::{ 6*4883830eSBenno Lossin braced, 7*4883830eSBenno Lossin parse::{End, Parse}, 8*4883830eSBenno Lossin parse_quote, 9*4883830eSBenno Lossin punctuated::Punctuated, 10*4883830eSBenno Lossin spanned::Spanned, 11*4883830eSBenno Lossin token, Block, Expr, ExprCall, ExprPath, Ident, Path, Token, Type, 12*4883830eSBenno Lossin }; 13*4883830eSBenno Lossin 14*4883830eSBenno Lossin use crate::diagnostics::{DiagCtxt, ErrorGuaranteed}; 15*4883830eSBenno Lossin 16*4883830eSBenno Lossin pub(crate) struct Initializer { 17*4883830eSBenno Lossin this: Option<This>, 18*4883830eSBenno Lossin path: Path, 19*4883830eSBenno Lossin brace_token: token::Brace, 20*4883830eSBenno Lossin fields: Punctuated<InitializerField, Token![,]>, 21*4883830eSBenno Lossin rest: Option<(Token![..], Expr)>, 22*4883830eSBenno Lossin error: Option<(Token![?], Type)>, 23*4883830eSBenno Lossin } 24*4883830eSBenno Lossin 25*4883830eSBenno Lossin struct This { 26*4883830eSBenno Lossin _and_token: Token![&], 27*4883830eSBenno Lossin ident: Ident, 28*4883830eSBenno Lossin _in_token: Token![in], 29*4883830eSBenno Lossin } 30*4883830eSBenno Lossin 31*4883830eSBenno Lossin enum InitializerField { 32*4883830eSBenno Lossin Value { 33*4883830eSBenno Lossin ident: Ident, 34*4883830eSBenno Lossin value: Option<(Token![:], Expr)>, 35*4883830eSBenno Lossin }, 36*4883830eSBenno Lossin Init { 37*4883830eSBenno Lossin ident: Ident, 38*4883830eSBenno Lossin _left_arrow_token: Token![<-], 39*4883830eSBenno Lossin value: Expr, 40*4883830eSBenno Lossin }, 41*4883830eSBenno Lossin Code { 42*4883830eSBenno Lossin _underscore_token: Token![_], 43*4883830eSBenno Lossin _colon_token: Token![:], 44*4883830eSBenno Lossin block: Block, 45*4883830eSBenno Lossin }, 46*4883830eSBenno Lossin } 47*4883830eSBenno Lossin 48*4883830eSBenno Lossin impl InitializerField { 49*4883830eSBenno Lossin fn ident(&self) -> Option<&Ident> { 50*4883830eSBenno Lossin match self { 51*4883830eSBenno Lossin Self::Value { ident, .. } | Self::Init { ident, .. } => Some(ident), 52*4883830eSBenno Lossin Self::Code { .. } => None, 53*4883830eSBenno Lossin } 54*4883830eSBenno Lossin } 55*4883830eSBenno Lossin } 56*4883830eSBenno Lossin 57*4883830eSBenno Lossin pub(crate) fn expand( 58*4883830eSBenno Lossin Initializer { 59*4883830eSBenno Lossin this, 60*4883830eSBenno Lossin path, 61*4883830eSBenno Lossin brace_token, 62*4883830eSBenno Lossin fields, 63*4883830eSBenno Lossin rest, 64*4883830eSBenno Lossin error, 65*4883830eSBenno Lossin }: Initializer, 66*4883830eSBenno Lossin default_error: Option<&'static str>, 67*4883830eSBenno Lossin pinned: bool, 68*4883830eSBenno Lossin dcx: &mut DiagCtxt, 69*4883830eSBenno Lossin ) -> Result<TokenStream, ErrorGuaranteed> { 70*4883830eSBenno Lossin let error = error.map_or_else( 71*4883830eSBenno Lossin || { 72*4883830eSBenno Lossin if let Some(default_error) = default_error { 73*4883830eSBenno Lossin syn::parse_str(default_error).unwrap() 74*4883830eSBenno Lossin } else { 75*4883830eSBenno Lossin dcx.error(brace_token.span.close(), "expected `? <type>` after `}`"); 76*4883830eSBenno Lossin parse_quote!(::core::convert::Infallible) 77*4883830eSBenno Lossin } 78*4883830eSBenno Lossin }, 79*4883830eSBenno Lossin |(_, err)| err, 80*4883830eSBenno Lossin ); 81*4883830eSBenno Lossin let slot = format_ident!("slot"); 82*4883830eSBenno Lossin let (has_data_trait, data_trait, get_data, init_from_closure) = if pinned { 83*4883830eSBenno Lossin ( 84*4883830eSBenno Lossin format_ident!("HasPinData"), 85*4883830eSBenno Lossin format_ident!("PinData"), 86*4883830eSBenno Lossin format_ident!("__pin_data"), 87*4883830eSBenno Lossin format_ident!("pin_init_from_closure"), 88*4883830eSBenno Lossin ) 89*4883830eSBenno Lossin } else { 90*4883830eSBenno Lossin ( 91*4883830eSBenno Lossin format_ident!("HasInitData"), 92*4883830eSBenno Lossin format_ident!("InitData"), 93*4883830eSBenno Lossin format_ident!("__init_data"), 94*4883830eSBenno Lossin format_ident!("init_from_closure"), 95*4883830eSBenno Lossin ) 96*4883830eSBenno Lossin }; 97*4883830eSBenno Lossin let init_kind = get_init_kind(rest, dcx); 98*4883830eSBenno Lossin let zeroable_check = match init_kind { 99*4883830eSBenno Lossin InitKind::Normal => quote!(), 100*4883830eSBenno Lossin InitKind::Zeroing => quote! { 101*4883830eSBenno Lossin // The user specified `..Zeroable::zeroed()` at the end of the list of fields. 102*4883830eSBenno Lossin // Therefore we check if the struct implements `Zeroable` and then zero the memory. 103*4883830eSBenno Lossin // This allows us to also remove the check that all fields are present (since we 104*4883830eSBenno Lossin // already set the memory to zero and that is a valid bit pattern). 105*4883830eSBenno Lossin fn assert_zeroable<T: ?::core::marker::Sized>(_: *mut T) 106*4883830eSBenno Lossin where T: ::pin_init::Zeroable 107*4883830eSBenno Lossin {} 108*4883830eSBenno Lossin // Ensure that the struct is indeed `Zeroable`. 109*4883830eSBenno Lossin assert_zeroable(#slot); 110*4883830eSBenno Lossin // SAFETY: The type implements `Zeroable` by the check above. 111*4883830eSBenno Lossin unsafe { ::core::ptr::write_bytes(#slot, 0, 1) }; 112*4883830eSBenno Lossin }, 113*4883830eSBenno Lossin }; 114*4883830eSBenno Lossin let this = match this { 115*4883830eSBenno Lossin None => quote!(), 116*4883830eSBenno Lossin Some(This { ident, .. }) => quote! { 117*4883830eSBenno Lossin // Create the `this` so it can be referenced by the user inside of the 118*4883830eSBenno Lossin // expressions creating the individual fields. 119*4883830eSBenno Lossin let #ident = unsafe { ::core::ptr::NonNull::new_unchecked(slot) }; 120*4883830eSBenno Lossin }, 121*4883830eSBenno Lossin }; 122*4883830eSBenno Lossin // `mixed_site` ensures that the data is not accessible to the user-controlled code. 123*4883830eSBenno Lossin let data = Ident::new("__data", Span::mixed_site()); 124*4883830eSBenno Lossin let init_fields = init_fields(&fields, pinned, &data, &slot); 125*4883830eSBenno Lossin let field_check = make_field_check(&fields, init_kind, &path); 126*4883830eSBenno Lossin Ok(quote! {{ 127*4883830eSBenno Lossin // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return 128*4883830eSBenno Lossin // type and shadow it later when we insert the arbitrary user code. That way there will be 129*4883830eSBenno Lossin // no possibility of returning without `unsafe`. 130*4883830eSBenno Lossin struct __InitOk; 131*4883830eSBenno Lossin 132*4883830eSBenno Lossin // Get the data about fields from the supplied type. 133*4883830eSBenno Lossin // SAFETY: TODO 134*4883830eSBenno Lossin let #data = unsafe { 135*4883830eSBenno Lossin use ::pin_init::__internal::#has_data_trait; 136*4883830eSBenno Lossin // Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit 137*4883830eSBenno Lossin // generics (which need to be present with that syntax). 138*4883830eSBenno Lossin #path::#get_data() 139*4883830eSBenno Lossin }; 140*4883830eSBenno Lossin // Ensure that `#data` really is of type `#data` and help with type inference: 141*4883830eSBenno Lossin let init = ::pin_init::__internal::#data_trait::make_closure::<_, __InitOk, #error>( 142*4883830eSBenno Lossin #data, 143*4883830eSBenno Lossin move |slot| { 144*4883830eSBenno Lossin { 145*4883830eSBenno Lossin // Shadow the structure so it cannot be used to return early. 146*4883830eSBenno Lossin struct __InitOk; 147*4883830eSBenno Lossin #zeroable_check 148*4883830eSBenno Lossin #this 149*4883830eSBenno Lossin #init_fields 150*4883830eSBenno Lossin #field_check 151*4883830eSBenno Lossin } 152*4883830eSBenno Lossin Ok(__InitOk) 153*4883830eSBenno Lossin } 154*4883830eSBenno Lossin ); 155*4883830eSBenno Lossin let init = move |slot| -> ::core::result::Result<(), #error> { 156*4883830eSBenno Lossin init(slot).map(|__InitOk| ()) 157*4883830eSBenno Lossin }; 158*4883830eSBenno Lossin // SAFETY: TODO 159*4883830eSBenno Lossin let init = unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }; 160*4883830eSBenno Lossin init 161*4883830eSBenno Lossin }}) 162*4883830eSBenno Lossin } 163*4883830eSBenno Lossin 164*4883830eSBenno Lossin enum InitKind { 165*4883830eSBenno Lossin Normal, 166*4883830eSBenno Lossin Zeroing, 167*4883830eSBenno Lossin } 168*4883830eSBenno Lossin 169*4883830eSBenno Lossin fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKind { 170*4883830eSBenno Lossin let Some((dotdot, expr)) = rest else { 171*4883830eSBenno Lossin return InitKind::Normal; 172*4883830eSBenno Lossin }; 173*4883830eSBenno Lossin match &expr { 174*4883830eSBenno Lossin Expr::Call(ExprCall { func, args, .. }) if args.is_empty() => match &**func { 175*4883830eSBenno Lossin Expr::Path(ExprPath { 176*4883830eSBenno Lossin attrs, 177*4883830eSBenno Lossin qself: None, 178*4883830eSBenno Lossin path: 179*4883830eSBenno Lossin Path { 180*4883830eSBenno Lossin leading_colon: None, 181*4883830eSBenno Lossin segments, 182*4883830eSBenno Lossin }, 183*4883830eSBenno Lossin }) if attrs.is_empty() 184*4883830eSBenno Lossin && segments.len() == 2 185*4883830eSBenno Lossin && segments[0].ident == "Zeroable" 186*4883830eSBenno Lossin && segments[0].arguments.is_none() 187*4883830eSBenno Lossin && segments[1].ident == "init_zeroed" 188*4883830eSBenno Lossin && segments[1].arguments.is_none() => 189*4883830eSBenno Lossin { 190*4883830eSBenno Lossin return InitKind::Zeroing; 191*4883830eSBenno Lossin } 192*4883830eSBenno Lossin _ => {} 193*4883830eSBenno Lossin }, 194*4883830eSBenno Lossin _ => {} 195*4883830eSBenno Lossin } 196*4883830eSBenno Lossin dcx.error( 197*4883830eSBenno Lossin dotdot.span().join(expr.span()).unwrap_or(expr.span()), 198*4883830eSBenno Lossin "expected nothing or `..Zeroable::init_zeroed()`.", 199*4883830eSBenno Lossin ); 200*4883830eSBenno Lossin InitKind::Normal 201*4883830eSBenno Lossin } 202*4883830eSBenno Lossin 203*4883830eSBenno Lossin /// Generate the code that initializes the fields of the struct using the initializers in `field`. 204*4883830eSBenno Lossin fn init_fields( 205*4883830eSBenno Lossin fields: &Punctuated<InitializerField, Token![,]>, 206*4883830eSBenno Lossin pinned: bool, 207*4883830eSBenno Lossin data: &Ident, 208*4883830eSBenno Lossin slot: &Ident, 209*4883830eSBenno Lossin ) -> TokenStream { 210*4883830eSBenno Lossin let mut guards = vec![]; 211*4883830eSBenno Lossin let mut res = TokenStream::new(); 212*4883830eSBenno Lossin for field in fields { 213*4883830eSBenno Lossin let init = match field { 214*4883830eSBenno Lossin InitializerField::Value { ident, value } => { 215*4883830eSBenno Lossin let mut value_ident = ident.clone(); 216*4883830eSBenno Lossin let value_prep = value.as_ref().map(|value| &value.1).map(|value| { 217*4883830eSBenno Lossin // Setting the span of `value_ident` to `value`'s span improves error messages 218*4883830eSBenno Lossin // when the type of `value` is wrong. 219*4883830eSBenno Lossin value_ident.set_span(value.span()); 220*4883830eSBenno Lossin quote!(let #value_ident = #value;) 221*4883830eSBenno Lossin }); 222*4883830eSBenno Lossin // Again span for better diagnostics 223*4883830eSBenno Lossin let write = quote_spanned!(ident.span()=> ::core::ptr::write); 224*4883830eSBenno Lossin let accessor = if pinned { 225*4883830eSBenno Lossin let project_ident = format_ident!("__project_{ident}"); 226*4883830eSBenno Lossin quote! { 227*4883830eSBenno Lossin // SAFETY: TODO 228*4883830eSBenno Lossin unsafe { #data.#project_ident(&mut (*#slot).#ident) } 229*4883830eSBenno Lossin } 230*4883830eSBenno Lossin } else { 231*4883830eSBenno Lossin quote! { 232*4883830eSBenno Lossin // SAFETY: TODO 233*4883830eSBenno Lossin unsafe { &mut (*#slot).#ident } 234*4883830eSBenno Lossin } 235*4883830eSBenno Lossin }; 236*4883830eSBenno Lossin quote! { 237*4883830eSBenno Lossin { 238*4883830eSBenno Lossin #value_prep 239*4883830eSBenno Lossin // SAFETY: TODO 240*4883830eSBenno Lossin unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) }; 241*4883830eSBenno Lossin } 242*4883830eSBenno Lossin #[allow(unused_variables)] 243*4883830eSBenno Lossin let #ident = #accessor; 244*4883830eSBenno Lossin } 245*4883830eSBenno Lossin } 246*4883830eSBenno Lossin InitializerField::Init { ident, value, .. } => { 247*4883830eSBenno Lossin // Again span for better diagnostics 248*4883830eSBenno Lossin let init = format_ident!("init", span = value.span()); 249*4883830eSBenno Lossin if pinned { 250*4883830eSBenno Lossin let project_ident = format_ident!("__project_{ident}"); 251*4883830eSBenno Lossin quote! { 252*4883830eSBenno Lossin { 253*4883830eSBenno Lossin let #init = #value; 254*4883830eSBenno Lossin // SAFETY: 255*4883830eSBenno Lossin // - `slot` is valid, because we are inside of an initializer closure, we 256*4883830eSBenno Lossin // return when an error/panic occurs. 257*4883830eSBenno Lossin // - We also use `#data` to require the correct trait (`Init` or `PinInit`) 258*4883830eSBenno Lossin // for `#ident`. 259*4883830eSBenno Lossin unsafe { #data.#ident(::core::ptr::addr_of_mut!((*#slot).#ident), #init)? }; 260*4883830eSBenno Lossin } 261*4883830eSBenno Lossin // SAFETY: TODO 262*4883830eSBenno Lossin #[allow(unused_variables)] 263*4883830eSBenno Lossin let #ident = unsafe { #data.#project_ident(&mut (*#slot).#ident) }; 264*4883830eSBenno Lossin } 265*4883830eSBenno Lossin } else { 266*4883830eSBenno Lossin quote! { 267*4883830eSBenno Lossin { 268*4883830eSBenno Lossin let #init = #value; 269*4883830eSBenno Lossin // SAFETY: `slot` is valid, because we are inside of an initializer 270*4883830eSBenno Lossin // closure, we return when an error/panic occurs. 271*4883830eSBenno Lossin unsafe { 272*4883830eSBenno Lossin ::pin_init::Init::__init( 273*4883830eSBenno Lossin #init, 274*4883830eSBenno Lossin ::core::ptr::addr_of_mut!((*#slot).#ident), 275*4883830eSBenno Lossin )? 276*4883830eSBenno Lossin }; 277*4883830eSBenno Lossin } 278*4883830eSBenno Lossin // SAFETY: TODO 279*4883830eSBenno Lossin #[allow(unused_variables)] 280*4883830eSBenno Lossin let #ident = unsafe { &mut (*#slot).#ident }; 281*4883830eSBenno Lossin } 282*4883830eSBenno Lossin } 283*4883830eSBenno Lossin } 284*4883830eSBenno Lossin InitializerField::Code { block: value, .. } => quote!(#[allow(unused_braces)] #value), 285*4883830eSBenno Lossin }; 286*4883830eSBenno Lossin res.extend(init); 287*4883830eSBenno Lossin if let Some(ident) = field.ident() { 288*4883830eSBenno Lossin // `mixed_site` ensures that the guard is not accessible to the user-controlled code. 289*4883830eSBenno Lossin let guard = format_ident!("__{ident}_guard", span = Span::mixed_site()); 290*4883830eSBenno Lossin guards.push(guard.clone()); 291*4883830eSBenno Lossin res.extend(quote! { 292*4883830eSBenno Lossin // Create the drop guard: 293*4883830eSBenno Lossin // 294*4883830eSBenno Lossin // We rely on macro hygiene to make it impossible for users to access this local 295*4883830eSBenno Lossin // variable. 296*4883830eSBenno Lossin // SAFETY: We forget the guard later when initialization has succeeded. 297*4883830eSBenno Lossin let #guard = unsafe { 298*4883830eSBenno Lossin ::pin_init::__internal::DropGuard::new( 299*4883830eSBenno Lossin ::core::ptr::addr_of_mut!((*slot).#ident) 300*4883830eSBenno Lossin ) 301*4883830eSBenno Lossin }; 302*4883830eSBenno Lossin }); 303*4883830eSBenno Lossin } 304*4883830eSBenno Lossin } 305*4883830eSBenno Lossin quote! { 306*4883830eSBenno Lossin #res 307*4883830eSBenno Lossin // If execution reaches this point, all fields have been initialized. Therefore we can now 308*4883830eSBenno Lossin // dismiss the guards by forgetting them. 309*4883830eSBenno Lossin #(::core::mem::forget(#guards);)* 310*4883830eSBenno Lossin } 311*4883830eSBenno Lossin } 312*4883830eSBenno Lossin 313*4883830eSBenno Lossin /// Generate the check for ensuring that every field has been initialized. 314*4883830eSBenno Lossin fn make_field_check( 315*4883830eSBenno Lossin fields: &Punctuated<InitializerField, Token![,]>, 316*4883830eSBenno Lossin init_kind: InitKind, 317*4883830eSBenno Lossin path: &Path, 318*4883830eSBenno Lossin ) -> TokenStream { 319*4883830eSBenno Lossin let fields = fields.iter().filter_map(|f| f.ident()); 320*4883830eSBenno Lossin match init_kind { 321*4883830eSBenno Lossin InitKind::Normal => quote! { 322*4883830eSBenno Lossin // We use unreachable code to ensure that all fields have been mentioned exactly once, 323*4883830eSBenno Lossin // this struct initializer will still be type-checked and complain with a very natural 324*4883830eSBenno Lossin // error message if a field is forgotten/mentioned more than once. 325*4883830eSBenno Lossin #[allow(unreachable_code, clippy::diverging_sub_expression)] 326*4883830eSBenno Lossin // SAFETY: this code is never executed. 327*4883830eSBenno Lossin let _ = || unsafe { 328*4883830eSBenno Lossin ::core::ptr::write(slot, #path { 329*4883830eSBenno Lossin #( 330*4883830eSBenno Lossin #fields: ::core::panic!(), 331*4883830eSBenno Lossin )* 332*4883830eSBenno Lossin }) 333*4883830eSBenno Lossin }; 334*4883830eSBenno Lossin }, 335*4883830eSBenno Lossin InitKind::Zeroing => quote! { 336*4883830eSBenno Lossin // We use unreachable code to ensure that all fields have been mentioned at most once. 337*4883830eSBenno Lossin // Since the user specified `..Zeroable::zeroed()` at the end, all missing fields will 338*4883830eSBenno Lossin // be zeroed. This struct initializer will still be type-checked and complain with a 339*4883830eSBenno Lossin // very natural error message if a field is mentioned more than once, or doesn't exist. 340*4883830eSBenno Lossin #[allow(unreachable_code, clippy::diverging_sub_expression, unused_assignments)] 341*4883830eSBenno Lossin // SAFETY: this code is never executed. 342*4883830eSBenno Lossin let _ = || unsafe { 343*4883830eSBenno Lossin let mut zeroed = ::core::mem::zeroed(); 344*4883830eSBenno Lossin // We have to use type inference here to make zeroed have the correct type. This 345*4883830eSBenno Lossin // does not get executed, so it has no effect. 346*4883830eSBenno Lossin ::core::ptr::write(slot, zeroed); 347*4883830eSBenno Lossin zeroed = ::core::mem::zeroed(); 348*4883830eSBenno Lossin ::core::ptr::write(slot, #path { 349*4883830eSBenno Lossin #( 350*4883830eSBenno Lossin #fields: ::core::panic!(), 351*4883830eSBenno Lossin )* 352*4883830eSBenno Lossin ..zeroed 353*4883830eSBenno Lossin }) 354*4883830eSBenno Lossin }; 355*4883830eSBenno Lossin }, 356*4883830eSBenno Lossin } 357*4883830eSBenno Lossin } 358*4883830eSBenno Lossin 359*4883830eSBenno Lossin impl Parse for Initializer { 360*4883830eSBenno Lossin fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> { 361*4883830eSBenno Lossin let this = input.peek(Token![&]).then(|| input.parse()).transpose()?; 362*4883830eSBenno Lossin let path = input.parse()?; 363*4883830eSBenno Lossin let content; 364*4883830eSBenno Lossin let brace_token = braced!(content in input); 365*4883830eSBenno Lossin let mut fields = Punctuated::new(); 366*4883830eSBenno Lossin loop { 367*4883830eSBenno Lossin let lh = content.lookahead1(); 368*4883830eSBenno Lossin if lh.peek(End) || lh.peek(Token![..]) { 369*4883830eSBenno Lossin break; 370*4883830eSBenno Lossin } else if lh.peek(Ident) || lh.peek(Token![_]) { 371*4883830eSBenno Lossin fields.push_value(content.parse()?); 372*4883830eSBenno Lossin let lh = content.lookahead1(); 373*4883830eSBenno Lossin if lh.peek(End) { 374*4883830eSBenno Lossin break; 375*4883830eSBenno Lossin } else if lh.peek(Token![,]) { 376*4883830eSBenno Lossin fields.push_punct(content.parse()?); 377*4883830eSBenno Lossin } else { 378*4883830eSBenno Lossin return Err(lh.error()); 379*4883830eSBenno Lossin } 380*4883830eSBenno Lossin } else { 381*4883830eSBenno Lossin return Err(lh.error()); 382*4883830eSBenno Lossin } 383*4883830eSBenno Lossin } 384*4883830eSBenno Lossin let rest = content 385*4883830eSBenno Lossin .peek(Token![..]) 386*4883830eSBenno Lossin .then(|| Ok::<_, syn::Error>((content.parse()?, content.parse()?))) 387*4883830eSBenno Lossin .transpose()?; 388*4883830eSBenno Lossin let error = input 389*4883830eSBenno Lossin .peek(Token![?]) 390*4883830eSBenno Lossin .then(|| Ok::<_, syn::Error>((input.parse()?, input.parse()?))) 391*4883830eSBenno Lossin .transpose()?; 392*4883830eSBenno Lossin Ok(Self { 393*4883830eSBenno Lossin this, 394*4883830eSBenno Lossin path, 395*4883830eSBenno Lossin brace_token, 396*4883830eSBenno Lossin fields, 397*4883830eSBenno Lossin rest, 398*4883830eSBenno Lossin error, 399*4883830eSBenno Lossin }) 400*4883830eSBenno Lossin } 401*4883830eSBenno Lossin } 402*4883830eSBenno Lossin 403*4883830eSBenno Lossin impl Parse for This { 404*4883830eSBenno Lossin fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> { 405*4883830eSBenno Lossin Ok(Self { 406*4883830eSBenno Lossin _and_token: input.parse()?, 407*4883830eSBenno Lossin ident: input.parse()?, 408*4883830eSBenno Lossin _in_token: input.parse()?, 409*4883830eSBenno Lossin }) 410*4883830eSBenno Lossin } 411*4883830eSBenno Lossin } 412*4883830eSBenno Lossin 413*4883830eSBenno Lossin impl Parse for InitializerField { 414*4883830eSBenno Lossin fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> { 415*4883830eSBenno Lossin let lh = input.lookahead1(); 416*4883830eSBenno Lossin if lh.peek(Token![_]) { 417*4883830eSBenno Lossin Ok(Self::Code { 418*4883830eSBenno Lossin _underscore_token: input.parse()?, 419*4883830eSBenno Lossin _colon_token: input.parse()?, 420*4883830eSBenno Lossin block: input.parse()?, 421*4883830eSBenno Lossin }) 422*4883830eSBenno Lossin } else if lh.peek(Ident) { 423*4883830eSBenno Lossin let ident = input.parse()?; 424*4883830eSBenno Lossin let lh = input.lookahead1(); 425*4883830eSBenno Lossin if lh.peek(Token![<-]) { 426*4883830eSBenno Lossin Ok(Self::Init { 427*4883830eSBenno Lossin ident, 428*4883830eSBenno Lossin _left_arrow_token: input.parse()?, 429*4883830eSBenno Lossin value: input.parse()?, 430*4883830eSBenno Lossin }) 431*4883830eSBenno Lossin } else if lh.peek(Token![:]) { 432*4883830eSBenno Lossin Ok(Self::Value { 433*4883830eSBenno Lossin ident, 434*4883830eSBenno Lossin value: Some((input.parse()?, input.parse()?)), 435*4883830eSBenno Lossin }) 436*4883830eSBenno Lossin } else if lh.peek(Token![,]) || lh.peek(End) { 437*4883830eSBenno Lossin Ok(Self::Value { ident, value: None }) 438*4883830eSBenno Lossin } else { 439*4883830eSBenno Lossin Err(lh.error()) 440*4883830eSBenno Lossin } 441*4883830eSBenno Lossin } else { 442*4883830eSBenno Lossin Err(lh.error()) 443*4883830eSBenno Lossin } 444*4883830eSBenno Lossin } 445*4883830eSBenno Lossin } 446