xref: /linux/rust/pin-init/internal/src/init.rs (revision 4883830e9784bdf6223fe0e5f1ea36d4a4ab4fef)
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