xref: /linux/rust/pin-init/internal/src/init.rs (revision aeabc92eb2d8c27578274a7ec3d0d00558fedfc2)
14883830eSBenno Lossin // SPDX-License-Identifier: Apache-2.0 OR MIT
24883830eSBenno Lossin 
34883830eSBenno Lossin use proc_macro2::{Span, TokenStream};
44883830eSBenno Lossin use quote::{format_ident, quote, quote_spanned};
54883830eSBenno Lossin use syn::{
64883830eSBenno Lossin     braced,
74883830eSBenno Lossin     parse::{End, Parse},
84883830eSBenno Lossin     parse_quote,
94883830eSBenno Lossin     punctuated::Punctuated,
104883830eSBenno Lossin     spanned::Spanned,
11*aeabc92eSBenno Lossin     token, Attribute, Block, Expr, ExprCall, ExprPath, Ident, Path, Token, Type,
124883830eSBenno Lossin };
134883830eSBenno Lossin 
144883830eSBenno Lossin use crate::diagnostics::{DiagCtxt, ErrorGuaranteed};
154883830eSBenno Lossin 
164883830eSBenno Lossin pub(crate) struct Initializer {
17*aeabc92eSBenno Lossin     attrs: Vec<InitializerAttribute>,
184883830eSBenno Lossin     this: Option<This>,
194883830eSBenno Lossin     path: Path,
204883830eSBenno Lossin     brace_token: token::Brace,
214883830eSBenno Lossin     fields: Punctuated<InitializerField, Token![,]>,
224883830eSBenno Lossin     rest: Option<(Token![..], Expr)>,
234883830eSBenno Lossin     error: Option<(Token![?], Type)>,
244883830eSBenno Lossin }
254883830eSBenno Lossin 
264883830eSBenno Lossin struct This {
274883830eSBenno Lossin     _and_token: Token![&],
284883830eSBenno Lossin     ident: Ident,
294883830eSBenno Lossin     _in_token: Token![in],
304883830eSBenno Lossin }
314883830eSBenno Lossin 
324883830eSBenno Lossin enum InitializerField {
334883830eSBenno Lossin     Value {
344883830eSBenno Lossin         ident: Ident,
354883830eSBenno Lossin         value: Option<(Token![:], Expr)>,
364883830eSBenno Lossin     },
374883830eSBenno Lossin     Init {
384883830eSBenno Lossin         ident: Ident,
394883830eSBenno Lossin         _left_arrow_token: Token![<-],
404883830eSBenno Lossin         value: Expr,
414883830eSBenno Lossin     },
424883830eSBenno Lossin     Code {
434883830eSBenno Lossin         _underscore_token: Token![_],
444883830eSBenno Lossin         _colon_token: Token![:],
454883830eSBenno Lossin         block: Block,
464883830eSBenno Lossin     },
474883830eSBenno Lossin }
484883830eSBenno Lossin 
494883830eSBenno Lossin impl InitializerField {
504883830eSBenno Lossin     fn ident(&self) -> Option<&Ident> {
514883830eSBenno Lossin         match self {
524883830eSBenno Lossin             Self::Value { ident, .. } | Self::Init { ident, .. } => Some(ident),
534883830eSBenno Lossin             Self::Code { .. } => None,
544883830eSBenno Lossin         }
554883830eSBenno Lossin     }
564883830eSBenno Lossin }
574883830eSBenno Lossin 
58*aeabc92eSBenno Lossin enum InitializerAttribute {
59*aeabc92eSBenno Lossin     DefaultError(DefaultErrorAttribute),
60*aeabc92eSBenno Lossin }
61*aeabc92eSBenno Lossin 
62*aeabc92eSBenno Lossin struct DefaultErrorAttribute {
63*aeabc92eSBenno Lossin     ty: Box<Type>,
64*aeabc92eSBenno Lossin }
65*aeabc92eSBenno Lossin 
664883830eSBenno Lossin pub(crate) fn expand(
674883830eSBenno Lossin     Initializer {
68*aeabc92eSBenno Lossin         attrs,
694883830eSBenno Lossin         this,
704883830eSBenno Lossin         path,
714883830eSBenno Lossin         brace_token,
724883830eSBenno Lossin         fields,
734883830eSBenno Lossin         rest,
744883830eSBenno Lossin         error,
754883830eSBenno Lossin     }: Initializer,
764883830eSBenno Lossin     default_error: Option<&'static str>,
774883830eSBenno Lossin     pinned: bool,
784883830eSBenno Lossin     dcx: &mut DiagCtxt,
794883830eSBenno Lossin ) -> Result<TokenStream, ErrorGuaranteed> {
804883830eSBenno Lossin     let error = error.map_or_else(
814883830eSBenno Lossin         || {
82*aeabc92eSBenno Lossin             if let Some(default_error) = attrs.iter().fold(None, |acc, attr| {
83*aeabc92eSBenno Lossin                 #[expect(irrefutable_let_patterns)]
84*aeabc92eSBenno Lossin                 if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr {
85*aeabc92eSBenno Lossin                     Some(ty.clone())
86*aeabc92eSBenno Lossin                 } else {
87*aeabc92eSBenno Lossin                     acc
88*aeabc92eSBenno Lossin                 }
89*aeabc92eSBenno Lossin             }) {
90*aeabc92eSBenno Lossin                 default_error
91*aeabc92eSBenno Lossin             } else if let Some(default_error) = default_error {
924883830eSBenno Lossin                 syn::parse_str(default_error).unwrap()
934883830eSBenno Lossin             } else {
944883830eSBenno Lossin                 dcx.error(brace_token.span.close(), "expected `? <type>` after `}`");
954883830eSBenno Lossin                 parse_quote!(::core::convert::Infallible)
964883830eSBenno Lossin             }
974883830eSBenno Lossin         },
98*aeabc92eSBenno Lossin         |(_, err)| Box::new(err),
994883830eSBenno Lossin     );
1004883830eSBenno Lossin     let slot = format_ident!("slot");
1014883830eSBenno Lossin     let (has_data_trait, data_trait, get_data, init_from_closure) = if pinned {
1024883830eSBenno Lossin         (
1034883830eSBenno Lossin             format_ident!("HasPinData"),
1044883830eSBenno Lossin             format_ident!("PinData"),
1054883830eSBenno Lossin             format_ident!("__pin_data"),
1064883830eSBenno Lossin             format_ident!("pin_init_from_closure"),
1074883830eSBenno Lossin         )
1084883830eSBenno Lossin     } else {
1094883830eSBenno Lossin         (
1104883830eSBenno Lossin             format_ident!("HasInitData"),
1114883830eSBenno Lossin             format_ident!("InitData"),
1124883830eSBenno Lossin             format_ident!("__init_data"),
1134883830eSBenno Lossin             format_ident!("init_from_closure"),
1144883830eSBenno Lossin         )
1154883830eSBenno Lossin     };
1164883830eSBenno Lossin     let init_kind = get_init_kind(rest, dcx);
1174883830eSBenno Lossin     let zeroable_check = match init_kind {
1184883830eSBenno Lossin         InitKind::Normal => quote!(),
1194883830eSBenno Lossin         InitKind::Zeroing => quote! {
1204883830eSBenno Lossin             // The user specified `..Zeroable::zeroed()` at the end of the list of fields.
1214883830eSBenno Lossin             // Therefore we check if the struct implements `Zeroable` and then zero the memory.
1224883830eSBenno Lossin             // This allows us to also remove the check that all fields are present (since we
1234883830eSBenno Lossin             // already set the memory to zero and that is a valid bit pattern).
1244883830eSBenno Lossin             fn assert_zeroable<T: ?::core::marker::Sized>(_: *mut T)
1254883830eSBenno Lossin             where T: ::pin_init::Zeroable
1264883830eSBenno Lossin             {}
1274883830eSBenno Lossin             // Ensure that the struct is indeed `Zeroable`.
1284883830eSBenno Lossin             assert_zeroable(#slot);
1294883830eSBenno Lossin             // SAFETY: The type implements `Zeroable` by the check above.
1304883830eSBenno Lossin             unsafe { ::core::ptr::write_bytes(#slot, 0, 1) };
1314883830eSBenno Lossin         },
1324883830eSBenno Lossin     };
1334883830eSBenno Lossin     let this = match this {
1344883830eSBenno Lossin         None => quote!(),
1354883830eSBenno Lossin         Some(This { ident, .. }) => quote! {
1364883830eSBenno Lossin             // Create the `this` so it can be referenced by the user inside of the
1374883830eSBenno Lossin             // expressions creating the individual fields.
1384883830eSBenno Lossin             let #ident = unsafe { ::core::ptr::NonNull::new_unchecked(slot) };
1394883830eSBenno Lossin         },
1404883830eSBenno Lossin     };
1414883830eSBenno Lossin     // `mixed_site` ensures that the data is not accessible to the user-controlled code.
1424883830eSBenno Lossin     let data = Ident::new("__data", Span::mixed_site());
1434883830eSBenno Lossin     let init_fields = init_fields(&fields, pinned, &data, &slot);
1444883830eSBenno Lossin     let field_check = make_field_check(&fields, init_kind, &path);
1454883830eSBenno Lossin     Ok(quote! {{
1464883830eSBenno Lossin         // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
1474883830eSBenno Lossin         // type and shadow it later when we insert the arbitrary user code. That way there will be
1484883830eSBenno Lossin         // no possibility of returning without `unsafe`.
1494883830eSBenno Lossin         struct __InitOk;
1504883830eSBenno Lossin 
1514883830eSBenno Lossin         // Get the data about fields from the supplied type.
1524883830eSBenno Lossin         // SAFETY: TODO
1534883830eSBenno Lossin         let #data = unsafe {
1544883830eSBenno Lossin             use ::pin_init::__internal::#has_data_trait;
1554883830eSBenno Lossin             // Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit
1564883830eSBenno Lossin             // generics (which need to be present with that syntax).
1574883830eSBenno Lossin             #path::#get_data()
1584883830eSBenno Lossin         };
1594883830eSBenno Lossin         // Ensure that `#data` really is of type `#data` and help with type inference:
1604883830eSBenno Lossin         let init = ::pin_init::__internal::#data_trait::make_closure::<_, __InitOk, #error>(
1614883830eSBenno Lossin             #data,
1624883830eSBenno Lossin             move |slot| {
1634883830eSBenno Lossin                 {
1644883830eSBenno Lossin                     // Shadow the structure so it cannot be used to return early.
1654883830eSBenno Lossin                     struct __InitOk;
1664883830eSBenno Lossin                     #zeroable_check
1674883830eSBenno Lossin                     #this
1684883830eSBenno Lossin                     #init_fields
1694883830eSBenno Lossin                     #field_check
1704883830eSBenno Lossin                 }
1714883830eSBenno Lossin                 Ok(__InitOk)
1724883830eSBenno Lossin             }
1734883830eSBenno Lossin         );
1744883830eSBenno Lossin         let init = move |slot| -> ::core::result::Result<(), #error> {
1754883830eSBenno Lossin             init(slot).map(|__InitOk| ())
1764883830eSBenno Lossin         };
1774883830eSBenno Lossin         // SAFETY: TODO
1784883830eSBenno Lossin         let init = unsafe { ::pin_init::#init_from_closure::<_, #error>(init) };
1794883830eSBenno Lossin         init
1804883830eSBenno Lossin     }})
1814883830eSBenno Lossin }
1824883830eSBenno Lossin 
1834883830eSBenno Lossin enum InitKind {
1844883830eSBenno Lossin     Normal,
1854883830eSBenno Lossin     Zeroing,
1864883830eSBenno Lossin }
1874883830eSBenno Lossin 
1884883830eSBenno Lossin fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKind {
1894883830eSBenno Lossin     let Some((dotdot, expr)) = rest else {
1904883830eSBenno Lossin         return InitKind::Normal;
1914883830eSBenno Lossin     };
1924883830eSBenno Lossin     match &expr {
1934883830eSBenno Lossin         Expr::Call(ExprCall { func, args, .. }) if args.is_empty() => match &**func {
1944883830eSBenno Lossin             Expr::Path(ExprPath {
1954883830eSBenno Lossin                 attrs,
1964883830eSBenno Lossin                 qself: None,
1974883830eSBenno Lossin                 path:
1984883830eSBenno Lossin                     Path {
1994883830eSBenno Lossin                         leading_colon: None,
2004883830eSBenno Lossin                         segments,
2014883830eSBenno Lossin                     },
2024883830eSBenno Lossin             }) if attrs.is_empty()
2034883830eSBenno Lossin                 && segments.len() == 2
2044883830eSBenno Lossin                 && segments[0].ident == "Zeroable"
2054883830eSBenno Lossin                 && segments[0].arguments.is_none()
2064883830eSBenno Lossin                 && segments[1].ident == "init_zeroed"
2074883830eSBenno Lossin                 && segments[1].arguments.is_none() =>
2084883830eSBenno Lossin             {
2094883830eSBenno Lossin                 return InitKind::Zeroing;
2104883830eSBenno Lossin             }
2114883830eSBenno Lossin             _ => {}
2124883830eSBenno Lossin         },
2134883830eSBenno Lossin         _ => {}
2144883830eSBenno Lossin     }
2154883830eSBenno Lossin     dcx.error(
2164883830eSBenno Lossin         dotdot.span().join(expr.span()).unwrap_or(expr.span()),
2174883830eSBenno Lossin         "expected nothing or `..Zeroable::init_zeroed()`.",
2184883830eSBenno Lossin     );
2194883830eSBenno Lossin     InitKind::Normal
2204883830eSBenno Lossin }
2214883830eSBenno Lossin 
2224883830eSBenno Lossin /// Generate the code that initializes the fields of the struct using the initializers in `field`.
2234883830eSBenno Lossin fn init_fields(
2244883830eSBenno Lossin     fields: &Punctuated<InitializerField, Token![,]>,
2254883830eSBenno Lossin     pinned: bool,
2264883830eSBenno Lossin     data: &Ident,
2274883830eSBenno Lossin     slot: &Ident,
2284883830eSBenno Lossin ) -> TokenStream {
2294883830eSBenno Lossin     let mut guards = vec![];
2304883830eSBenno Lossin     let mut res = TokenStream::new();
2314883830eSBenno Lossin     for field in fields {
2324883830eSBenno Lossin         let init = match field {
2334883830eSBenno Lossin             InitializerField::Value { ident, value } => {
2344883830eSBenno Lossin                 let mut value_ident = ident.clone();
2354883830eSBenno Lossin                 let value_prep = value.as_ref().map(|value| &value.1).map(|value| {
2364883830eSBenno Lossin                     // Setting the span of `value_ident` to `value`'s span improves error messages
2374883830eSBenno Lossin                     // when the type of `value` is wrong.
2384883830eSBenno Lossin                     value_ident.set_span(value.span());
2394883830eSBenno Lossin                     quote!(let #value_ident = #value;)
2404883830eSBenno Lossin                 });
2414883830eSBenno Lossin                 // Again span for better diagnostics
2424883830eSBenno Lossin                 let write = quote_spanned!(ident.span()=> ::core::ptr::write);
2434883830eSBenno Lossin                 let accessor = if pinned {
2444883830eSBenno Lossin                     let project_ident = format_ident!("__project_{ident}");
2454883830eSBenno Lossin                     quote! {
2464883830eSBenno Lossin                         // SAFETY: TODO
2474883830eSBenno Lossin                         unsafe { #data.#project_ident(&mut (*#slot).#ident) }
2484883830eSBenno Lossin                     }
2494883830eSBenno Lossin                 } else {
2504883830eSBenno Lossin                     quote! {
2514883830eSBenno Lossin                         // SAFETY: TODO
2524883830eSBenno Lossin                         unsafe { &mut (*#slot).#ident }
2534883830eSBenno Lossin                     }
2544883830eSBenno Lossin                 };
2554883830eSBenno Lossin                 quote! {
2564883830eSBenno Lossin                     {
2574883830eSBenno Lossin                         #value_prep
2584883830eSBenno Lossin                         // SAFETY: TODO
2594883830eSBenno Lossin                         unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };
2604883830eSBenno Lossin                     }
2614883830eSBenno Lossin                     #[allow(unused_variables)]
2624883830eSBenno Lossin                     let #ident = #accessor;
2634883830eSBenno Lossin                 }
2644883830eSBenno Lossin             }
2654883830eSBenno Lossin             InitializerField::Init { ident, value, .. } => {
2664883830eSBenno Lossin                 // Again span for better diagnostics
2674883830eSBenno Lossin                 let init = format_ident!("init", span = value.span());
2684883830eSBenno Lossin                 if pinned {
2694883830eSBenno Lossin                     let project_ident = format_ident!("__project_{ident}");
2704883830eSBenno Lossin                     quote! {
2714883830eSBenno Lossin                         {
2724883830eSBenno Lossin                             let #init = #value;
2734883830eSBenno Lossin                             // SAFETY:
2744883830eSBenno Lossin                             // - `slot` is valid, because we are inside of an initializer closure, we
2754883830eSBenno Lossin                             //   return when an error/panic occurs.
2764883830eSBenno Lossin                             // - We also use `#data` to require the correct trait (`Init` or `PinInit`)
2774883830eSBenno Lossin                             //   for `#ident`.
2784883830eSBenno Lossin                             unsafe { #data.#ident(::core::ptr::addr_of_mut!((*#slot).#ident), #init)? };
2794883830eSBenno Lossin                         }
2804883830eSBenno Lossin                         // SAFETY: TODO
2814883830eSBenno Lossin                         #[allow(unused_variables)]
2824883830eSBenno Lossin                         let #ident = unsafe { #data.#project_ident(&mut (*#slot).#ident) };
2834883830eSBenno Lossin                     }
2844883830eSBenno Lossin                 } else {
2854883830eSBenno Lossin                     quote! {
2864883830eSBenno Lossin                         {
2874883830eSBenno Lossin                             let #init = #value;
2884883830eSBenno Lossin                             // SAFETY: `slot` is valid, because we are inside of an initializer
2894883830eSBenno Lossin                             // closure, we return when an error/panic occurs.
2904883830eSBenno Lossin                             unsafe {
2914883830eSBenno Lossin                                 ::pin_init::Init::__init(
2924883830eSBenno Lossin                                     #init,
2934883830eSBenno Lossin                                     ::core::ptr::addr_of_mut!((*#slot).#ident),
2944883830eSBenno Lossin                                 )?
2954883830eSBenno Lossin                             };
2964883830eSBenno Lossin                         }
2974883830eSBenno Lossin                         // SAFETY: TODO
2984883830eSBenno Lossin                         #[allow(unused_variables)]
2994883830eSBenno Lossin                         let #ident = unsafe { &mut (*#slot).#ident };
3004883830eSBenno Lossin                     }
3014883830eSBenno Lossin                 }
3024883830eSBenno Lossin             }
3034883830eSBenno Lossin             InitializerField::Code { block: value, .. } => quote!(#[allow(unused_braces)] #value),
3044883830eSBenno Lossin         };
3054883830eSBenno Lossin         res.extend(init);
3064883830eSBenno Lossin         if let Some(ident) = field.ident() {
3074883830eSBenno Lossin             // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
3084883830eSBenno Lossin             let guard = format_ident!("__{ident}_guard", span = Span::mixed_site());
3094883830eSBenno Lossin             guards.push(guard.clone());
3104883830eSBenno Lossin             res.extend(quote! {
3114883830eSBenno Lossin                 // Create the drop guard:
3124883830eSBenno Lossin                 //
3134883830eSBenno Lossin                 // We rely on macro hygiene to make it impossible for users to access this local
3144883830eSBenno Lossin                 // variable.
3154883830eSBenno Lossin                 // SAFETY: We forget the guard later when initialization has succeeded.
3164883830eSBenno Lossin                 let #guard = unsafe {
3174883830eSBenno Lossin                     ::pin_init::__internal::DropGuard::new(
3184883830eSBenno Lossin                         ::core::ptr::addr_of_mut!((*slot).#ident)
3194883830eSBenno Lossin                     )
3204883830eSBenno Lossin                 };
3214883830eSBenno Lossin             });
3224883830eSBenno Lossin         }
3234883830eSBenno Lossin     }
3244883830eSBenno Lossin     quote! {
3254883830eSBenno Lossin         #res
3264883830eSBenno Lossin         // If execution reaches this point, all fields have been initialized. Therefore we can now
3274883830eSBenno Lossin         // dismiss the guards by forgetting them.
3284883830eSBenno Lossin         #(::core::mem::forget(#guards);)*
3294883830eSBenno Lossin     }
3304883830eSBenno Lossin }
3314883830eSBenno Lossin 
3324883830eSBenno Lossin /// Generate the check for ensuring that every field has been initialized.
3334883830eSBenno Lossin fn make_field_check(
3344883830eSBenno Lossin     fields: &Punctuated<InitializerField, Token![,]>,
3354883830eSBenno Lossin     init_kind: InitKind,
3364883830eSBenno Lossin     path: &Path,
3374883830eSBenno Lossin ) -> TokenStream {
3384883830eSBenno Lossin     let fields = fields.iter().filter_map(|f| f.ident());
3394883830eSBenno Lossin     match init_kind {
3404883830eSBenno Lossin         InitKind::Normal => quote! {
3414883830eSBenno Lossin             // We use unreachable code to ensure that all fields have been mentioned exactly once,
3424883830eSBenno Lossin             // this struct initializer will still be type-checked and complain with a very natural
3434883830eSBenno Lossin             // error message if a field is forgotten/mentioned more than once.
3444883830eSBenno Lossin             #[allow(unreachable_code, clippy::diverging_sub_expression)]
3454883830eSBenno Lossin             // SAFETY: this code is never executed.
3464883830eSBenno Lossin             let _ = || unsafe {
3474883830eSBenno Lossin                 ::core::ptr::write(slot, #path {
3484883830eSBenno Lossin                     #(
3494883830eSBenno Lossin                         #fields: ::core::panic!(),
3504883830eSBenno Lossin                     )*
3514883830eSBenno Lossin                 })
3524883830eSBenno Lossin             };
3534883830eSBenno Lossin         },
3544883830eSBenno Lossin         InitKind::Zeroing => quote! {
3554883830eSBenno Lossin             // We use unreachable code to ensure that all fields have been mentioned at most once.
3564883830eSBenno Lossin             // Since the user specified `..Zeroable::zeroed()` at the end, all missing fields will
3574883830eSBenno Lossin             // be zeroed. This struct initializer will still be type-checked and complain with a
3584883830eSBenno Lossin             // very natural error message if a field is mentioned more than once, or doesn't exist.
3594883830eSBenno Lossin             #[allow(unreachable_code, clippy::diverging_sub_expression, unused_assignments)]
3604883830eSBenno Lossin             // SAFETY: this code is never executed.
3614883830eSBenno Lossin             let _ = || unsafe {
3624883830eSBenno Lossin                 let mut zeroed = ::core::mem::zeroed();
3634883830eSBenno Lossin                 // We have to use type inference here to make zeroed have the correct type. This
3644883830eSBenno Lossin                 // does not get executed, so it has no effect.
3654883830eSBenno Lossin                 ::core::ptr::write(slot, zeroed);
3664883830eSBenno Lossin                 zeroed = ::core::mem::zeroed();
3674883830eSBenno Lossin                 ::core::ptr::write(slot, #path {
3684883830eSBenno Lossin                     #(
3694883830eSBenno Lossin                         #fields: ::core::panic!(),
3704883830eSBenno Lossin                     )*
3714883830eSBenno Lossin                     ..zeroed
3724883830eSBenno Lossin                 })
3734883830eSBenno Lossin             };
3744883830eSBenno Lossin         },
3754883830eSBenno Lossin     }
3764883830eSBenno Lossin }
3774883830eSBenno Lossin 
3784883830eSBenno Lossin impl Parse for Initializer {
3794883830eSBenno Lossin     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
380*aeabc92eSBenno Lossin         let attrs = input.call(Attribute::parse_outer)?;
3814883830eSBenno Lossin         let this = input.peek(Token![&]).then(|| input.parse()).transpose()?;
3824883830eSBenno Lossin         let path = input.parse()?;
3834883830eSBenno Lossin         let content;
3844883830eSBenno Lossin         let brace_token = braced!(content in input);
3854883830eSBenno Lossin         let mut fields = Punctuated::new();
3864883830eSBenno Lossin         loop {
3874883830eSBenno Lossin             let lh = content.lookahead1();
3884883830eSBenno Lossin             if lh.peek(End) || lh.peek(Token![..]) {
3894883830eSBenno Lossin                 break;
3904883830eSBenno Lossin             } else if lh.peek(Ident) || lh.peek(Token![_]) {
3914883830eSBenno Lossin                 fields.push_value(content.parse()?);
3924883830eSBenno Lossin                 let lh = content.lookahead1();
3934883830eSBenno Lossin                 if lh.peek(End) {
3944883830eSBenno Lossin                     break;
3954883830eSBenno Lossin                 } else if lh.peek(Token![,]) {
3964883830eSBenno Lossin                     fields.push_punct(content.parse()?);
3974883830eSBenno Lossin                 } else {
3984883830eSBenno Lossin                     return Err(lh.error());
3994883830eSBenno Lossin                 }
4004883830eSBenno Lossin             } else {
4014883830eSBenno Lossin                 return Err(lh.error());
4024883830eSBenno Lossin             }
4034883830eSBenno Lossin         }
4044883830eSBenno Lossin         let rest = content
4054883830eSBenno Lossin             .peek(Token![..])
4064883830eSBenno Lossin             .then(|| Ok::<_, syn::Error>((content.parse()?, content.parse()?)))
4074883830eSBenno Lossin             .transpose()?;
4084883830eSBenno Lossin         let error = input
4094883830eSBenno Lossin             .peek(Token![?])
4104883830eSBenno Lossin             .then(|| Ok::<_, syn::Error>((input.parse()?, input.parse()?)))
4114883830eSBenno Lossin             .transpose()?;
412*aeabc92eSBenno Lossin         let attrs = attrs
413*aeabc92eSBenno Lossin             .into_iter()
414*aeabc92eSBenno Lossin             .map(|a| {
415*aeabc92eSBenno Lossin                 if a.path().is_ident("default_error") {
416*aeabc92eSBenno Lossin                     a.parse_args::<DefaultErrorAttribute>()
417*aeabc92eSBenno Lossin                         .map(InitializerAttribute::DefaultError)
418*aeabc92eSBenno Lossin                 } else {
419*aeabc92eSBenno Lossin                     Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
420*aeabc92eSBenno Lossin                 }
421*aeabc92eSBenno Lossin             })
422*aeabc92eSBenno Lossin             .collect::<Result<Vec<_>, _>>()?;
4234883830eSBenno Lossin         Ok(Self {
424*aeabc92eSBenno Lossin             attrs,
4254883830eSBenno Lossin             this,
4264883830eSBenno Lossin             path,
4274883830eSBenno Lossin             brace_token,
4284883830eSBenno Lossin             fields,
4294883830eSBenno Lossin             rest,
4304883830eSBenno Lossin             error,
4314883830eSBenno Lossin         })
4324883830eSBenno Lossin     }
4334883830eSBenno Lossin }
4344883830eSBenno Lossin 
435*aeabc92eSBenno Lossin impl Parse for DefaultErrorAttribute {
436*aeabc92eSBenno Lossin     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
437*aeabc92eSBenno Lossin         Ok(Self { ty: input.parse()? })
438*aeabc92eSBenno Lossin     }
439*aeabc92eSBenno Lossin }
440*aeabc92eSBenno Lossin 
4414883830eSBenno Lossin impl Parse for This {
4424883830eSBenno Lossin     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
4434883830eSBenno Lossin         Ok(Self {
4444883830eSBenno Lossin             _and_token: input.parse()?,
4454883830eSBenno Lossin             ident: input.parse()?,
4464883830eSBenno Lossin             _in_token: input.parse()?,
4474883830eSBenno Lossin         })
4484883830eSBenno Lossin     }
4494883830eSBenno Lossin }
4504883830eSBenno Lossin 
4514883830eSBenno Lossin impl Parse for InitializerField {
4524883830eSBenno Lossin     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
4534883830eSBenno Lossin         let lh = input.lookahead1();
4544883830eSBenno Lossin         if lh.peek(Token![_]) {
4554883830eSBenno Lossin             Ok(Self::Code {
4564883830eSBenno Lossin                 _underscore_token: input.parse()?,
4574883830eSBenno Lossin                 _colon_token: input.parse()?,
4584883830eSBenno Lossin                 block: input.parse()?,
4594883830eSBenno Lossin             })
4604883830eSBenno Lossin         } else if lh.peek(Ident) {
4614883830eSBenno Lossin             let ident = input.parse()?;
4624883830eSBenno Lossin             let lh = input.lookahead1();
4634883830eSBenno Lossin             if lh.peek(Token![<-]) {
4644883830eSBenno Lossin                 Ok(Self::Init {
4654883830eSBenno Lossin                     ident,
4664883830eSBenno Lossin                     _left_arrow_token: input.parse()?,
4674883830eSBenno Lossin                     value: input.parse()?,
4684883830eSBenno Lossin                 })
4694883830eSBenno Lossin             } else if lh.peek(Token![:]) {
4704883830eSBenno Lossin                 Ok(Self::Value {
4714883830eSBenno Lossin                     ident,
4724883830eSBenno Lossin                     value: Some((input.parse()?, input.parse()?)),
4734883830eSBenno Lossin                 })
4744883830eSBenno Lossin             } else if lh.peek(Token![,]) || lh.peek(End) {
4754883830eSBenno Lossin                 Ok(Self::Value { ident, value: None })
4764883830eSBenno Lossin             } else {
4774883830eSBenno Lossin                 Err(lh.error())
4784883830eSBenno Lossin             }
4794883830eSBenno Lossin         } else {
4804883830eSBenno Lossin             Err(lh.error())
4814883830eSBenno Lossin         }
4824883830eSBenno Lossin     }
4834883830eSBenno Lossin }
484