xref: /linux/rust/pin-init/internal/src/init.rs (revision c7ec00c230b5014757a76f3f285c7fa880321163)
1 // SPDX-License-Identifier: Apache-2.0 OR MIT
2 
3 use proc_macro2::{Span, TokenStream};
4 use quote::{format_ident, quote, quote_spanned, ToTokens, TokenStreamExt};
5 use syn::{
6     braced, parenthesized,
7     parse::{End, Parse},
8     parse_quote,
9     punctuated::{Pair, Punctuated},
10     spanned::Spanned,
11     token, Attribute, Block, Expr, ExprCall, ExprPath, Ident, Index, LitInt, Member, Path, Token,
12     Type,
13 };
14 
15 use crate::{
16     diagnostics::{DiagCtxt, ErrorGuaranteed},
17     util::*,
18 };
19 
20 pub(crate) struct Initializer<Kind = InitExprKind> {
21     attrs: Vec<InitializerAttribute>,
22     this: Option<This>,
23     kind: Kind,
24     error: Option<(Token![?], Type)>,
25 }
26 
27 pub(crate) struct InitExprStruct {
28     path: Path,
29     brace_token: token::Brace,
30     fields: Punctuated<InitializerField, Token![,]>,
31     rest: Option<(Token![..], Expr)>,
32 }
33 
34 pub(crate) struct InitExprTuple {
35     path: Path,
36     paren_token: token::Paren,
37     fields: Punctuated<InitTupleField, Token![,]>,
38 }
39 
40 pub(crate) enum InitExprKind {
41     Struct(InitExprStruct),
42     Tuple(InitExprTuple),
43 }
44 
45 struct InitTupleField {
46     attrs: Vec<Attribute>,
47     value: Expr,
48 }
49 
50 impl InitExprTuple {
51     fn normalize(self) -> InitExprStruct {
52         let InitExprTuple {
53             path,
54             paren_token,
55             fields,
56         } = self;
57         InitExprStruct {
58             path,
59             brace_token: token::Brace {
60                 span: paren_token.span,
61             },
62             fields: fields
63                 .into_pairs()
64                 .enumerate()
65                 .map(|(index, pair)| {
66                     let (field, comma) = pair.into_tuple();
67                     let span = field.value.span();
68                     let field = InitializerField {
69                         attrs: field.attrs,
70                         kind: InitializerKind::Value {
71                             member: Member::Unnamed(Index {
72                                 index: index.try_into().unwrap(),
73                                 span,
74                             }),
75                             value: Some((Token![:](span), field.value)),
76                         },
77                     };
78                     Pair::new(field, comma)
79                 })
80                 .collect(),
81             rest: None,
82         }
83     }
84 }
85 
86 struct This {
87     _and_token: Token![&],
88     ident: Ident,
89     _in_token: Token![in],
90 }
91 
92 struct InitializerField {
93     attrs: Vec<Attribute>,
94     kind: InitializerKind,
95 }
96 
97 enum InitializerKind {
98     Value {
99         member: Member,
100         value: Option<(Token![:], Expr)>,
101     },
102     Init {
103         member: Member,
104         left_arrow_token: Token![<-],
105         value: Expr,
106     },
107     Code {
108         _underscore_token: Token![_],
109         _colon_token: Token![:],
110         block: Block,
111     },
112 }
113 
114 impl InitializerKind {
115     fn member(&self) -> Option<&Member> {
116         match self {
117             Self::Value { member, .. } | Self::Init { member, .. } => Some(member),
118             Self::Code { .. } => None,
119         }
120     }
121 }
122 
123 enum InitializerAttribute {
124     DefaultError(DefaultErrorAttribute),
125 }
126 
127 struct DefaultErrorAttribute {
128     ty: Box<Type>,
129 }
130 
131 pub(crate) fn expand_with_cfg(
132     initializer: Initializer,
133     default_error: Option<&'static str>,
134     pinned: bool,
135     dcx: &mut DiagCtxt,
136 ) -> Result<TokenStream, ErrorGuaranteed> {
137     let initializer = match initializer.kind {
138         InitExprKind::Tuple(expr) => {
139             let mut initializer = Initializer {
140                 attrs: initializer.attrs,
141                 this: initializer.this,
142                 kind: expr,
143                 error: initializer.error,
144             };
145 
146             // Removing a tuple field renumbers every field after it, which cannot be expressed with
147             // a `cfg` attribute on the initializer of a single field. Therefore, resolve tuple
148             // field cfgs before continuing. Struct expression syntax uses explicit numbers, so
149             // there is no need to pre-expand them and we only need to emit their cfgs on generated
150             // code.
151             for (field_idx, field) in initializer.kind.fields.iter_mut().enumerate() {
152                 let cfg = field.attrs.extract_cfg_attrs();
153 
154                 if cfg.is_empty() {
155                     continue;
156                 }
157 
158                 let true_initializer = initializer.to_token_stream();
159                 initializer.kind.fields = initializer
160                     .kind
161                     .fields
162                     .into_pairs()
163                     .enumerate()
164                     .filter(|&(index, _)| index != field_idx)
165                     .map(|(_, pair)| pair)
166                     .collect();
167 
168                 let false_initializer = &initializer;
169 
170                 let macro_name = if pinned {
171                     quote!(::pin_init::pin_init)
172                 } else {
173                     quote!(::pin_init::init)
174                 };
175 
176                 // Resolve one field at a time until we've got no more tuple field cfgs.
177                 //
178                 // This is linear time because macro invocations with false cfg will not be
179                 // expanded.
180                 return Ok(quote! {
181                     {
182                         // Use `{}` delimiter here so semicolon is not required, otherwise the
183                         // expression becomes unit type.
184                         #[cfg(all(#(#cfg,)*))]
185                         #macro_name! { #true_initializer }
186 
187                         #[cfg(not(all(#(#cfg,)*)))]
188                         #macro_name! { #false_initializer }
189                     }
190                 });
191             }
192 
193             // No cfgs left, we can normalize the initializer to the struct kind.
194             Initializer {
195                 attrs: initializer.attrs,
196                 this: initializer.this,
197                 kind: initializer.kind.normalize(),
198                 error: initializer.error,
199             }
200         }
201 
202         InitExprKind::Struct(expr) => Initializer {
203             attrs: initializer.attrs,
204             this: initializer.this,
205             kind: expr,
206             error: initializer.error,
207         },
208     };
209 
210     expand(initializer, default_error, pinned, dcx)
211 }
212 
213 fn expand(
214     Initializer {
215         attrs,
216         this,
217         kind:
218             InitExprStruct {
219                 path,
220                 brace_token,
221                 fields,
222                 rest,
223             },
224         error,
225     }: Initializer<InitExprStruct>,
226     default_error: Option<&'static str>,
227     pinned: bool,
228     dcx: &mut DiagCtxt,
229 ) -> Result<TokenStream, ErrorGuaranteed> {
230     let error = error.map_or_else(
231         || {
232             if let Some(default_error) = attrs.iter().fold(None, |acc, attr| {
233                 #[expect(irrefutable_let_patterns)]
234                 if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr {
235                     Some(ty.clone())
236                 } else {
237                     acc
238                 }
239             }) {
240                 default_error
241             } else if let Some(default_error) = default_error {
242                 syn::parse_str(default_error).unwrap()
243             } else {
244                 dcx.error(
245                     brace_token.span.close(),
246                     "expected `? <type>` after initializer",
247                 );
248                 parse_quote!(::core::convert::Infallible)
249             }
250         },
251         |(_, err)| Box::new(err),
252     );
253     let (get_pin_data, init_from_closure) = if pinned {
254         (
255             Some(
256                 quote_spanned! { path.span().resolved_at(Span::mixed_site()) =>
257                     let data = ::pin_init::__internal::HasPinData::__pin_data(data);
258                 },
259             ),
260             format_ident!("pin_init_from_closure"),
261         )
262     } else {
263         (None, format_ident!("init_from_closure"))
264     };
265     let init_kind = get_init_kind(rest, dcx);
266     let zeroable_check = match init_kind {
267         InitKind::Normal => quote!(),
268         InitKind::Zeroing => quote_spanned! { Span::mixed_site() =>
269             // The user specified `..Zeroable::zeroed()` at the end of the list of fields.
270             // Therefore we check if the struct implements `Zeroable` and then zero the memory.
271             // This allows us to also remove the check that all fields are present (since we
272             // already set the memory to zero and that is a valid bit pattern).
273             fn assert_zeroable<T: ?::core::marker::Sized>(_: *mut T)
274             where T: ::pin_init::Zeroable
275             {}
276             // Ensure that the struct is indeed `Zeroable`.
277             assert_zeroable(slot);
278             // SAFETY: The type implements `Zeroable` by the check above.
279             unsafe { ::core::ptr::write_bytes(slot, 0, 1) };
280         },
281     };
282     let this = match this {
283         None => quote!(),
284         Some(This { ident, .. }) => quote_spanned! { Span::mixed_site() =>
285             // Create the `this` so it can be referenced by the user inside of the
286             // expressions creating the individual fields.
287             let #ident = unsafe { ::core::ptr::NonNull::new_unchecked(slot) };
288         },
289     };
290     // `mixed_site` ensures that the data is not accessible to the user-controlled code.
291     let init_fields = make_field_init(&fields, pinned, false);
292     let drop_check = make_field_init(&fields, pinned, true);
293     let field_check = make_field_check(&fields, init_kind, &path);
294 
295     Ok(quote_spanned! { Span::mixed_site() => {
296         // Get the data about fields from the supplied type.
297         let data = {
298             use ::pin_init::__internal::HasInitData;
299             // Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit
300             // generics (which need to be present with that syntax).
301             #path::__init_data()
302         };
303 
304         #get_pin_data
305 
306         // Ensure that `data` really is of type `data` and help with type inference:
307         let init = data.__make_closure::<_, #error>(
308             move |slot, data_lt| {
309                 #zeroable_check
310                 #this
311                 // Generate init twice, which is mostly identical except for lifetimes.
312                 if true {
313                     // In this path, we use the field lifetime from HRTB to prevent environment
314                     // lifetime from entering the fields, and to ensure that the dependency of
315                     // fields is consistent with the field drop of the struct.
316                     #init_fields
317                 } else {
318                     // In this path, we use local lifetime, to make sure that if initialization
319                     // fails, the destructor execution will not cause lifetime issues. This is
320                     // separate as implied bounds between field lifetimes can be inconsistent with
321                     // that of the drop.
322                     #drop_check
323                 }
324                 #field_check
325                 // SAFETY: we are the `init!` macro that is allowed to call this.
326                 Ok(unsafe { ::pin_init::__internal::InitOk::new() })
327             }
328         );
329         let init = move |slot| -> ::core::result::Result<(), #error> {
330             init(slot, data.__with_lt()).map(|__InitOk| ())
331         };
332         // SAFETY: TODO
333         unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }
334     }})
335 }
336 
337 enum InitKind {
338     Normal,
339     Zeroing,
340 }
341 
342 fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKind {
343     let Some((dotdot, expr)) = rest else {
344         return InitKind::Normal;
345     };
346     match &expr {
347         Expr::Call(ExprCall { func, args, .. }) if args.is_empty() => match &**func {
348             Expr::Path(ExprPath {
349                 attrs,
350                 qself: None,
351                 path:
352                     Path {
353                         leading_colon: None,
354                         segments,
355                     },
356             }) if attrs.is_empty()
357                 && segments.len() == 2
358                 && segments[0].ident == "Zeroable"
359                 && segments[0].arguments.is_none()
360                 && segments[1].ident == "init_zeroed"
361                 && segments[1].arguments.is_none() =>
362             {
363                 return InitKind::Zeroing;
364             }
365             _ => {}
366         },
367         _ => {}
368     }
369     dcx.error(
370         dotdot.span().join(expr.span()).unwrap_or(expr.span()),
371         "expected nothing or `..Zeroable::init_zeroed()`.",
372     );
373     InitKind::Normal
374 }
375 
376 /// Generate the code that initializes the fields of the struct using the initializers in `field`.
377 fn make_field_init(
378     fields: &Punctuated<InitializerField, Token![,]>,
379     pinned: bool,
380     dropck: bool,
381 ) -> TokenStream {
382     let mut forget_guards = vec![];
383     let mut res = TokenStream::new();
384     for InitializerField { attrs, kind } in fields {
385         let cfgs = {
386             let mut cfgs = attrs.clone();
387             cfgs.retain(|attr| attr.path().is_ident("cfg"));
388             cfgs
389         };
390 
391         let member = match kind {
392             InitializerKind::Value { member, .. } => member,
393             InitializerKind::Init { member, .. } => member,
394             InitializerKind::Code { block, .. } => {
395                 let stmt = &block.stmts;
396                 res.extend(quote! {
397                     #(#attrs)*
398                     {
399                         #(#stmt)*
400                     }
401                 });
402                 continue;
403             }
404         };
405         let ident = member.as_ident();
406         let span = Span::mixed_site().located_at(ident.span());
407 
408         let slot = if pinned {
409             let data = if !dropck {
410                 quote_spanned!(span => data_lt)
411             } else {
412                 quote_spanned!(span => data.__with_lt())
413             };
414             quote_spanned! { span =>
415                 // SAFETY:
416                 // - `slot` is valid and properly aligned.
417                 // - `make_field_check` checks that `&raw mut (*slot).#member` is properly aligned.
418                 // - `make_field_check` prevents `#member` from being used twice, therefore
419                 //   `(*slot).#member` is exclusively accessed and has not been initialized.
420                 (unsafe { #data.#ident(slot) })
421             }
422         } else {
423             quote_spanned! { span =>
424                 // For `init!()` macro, everything is unpinned.
425                 // SAFETY:
426                 // - `&raw mut (*slot).#member` is valid.
427                 // - `make_field_check` checks that `&raw mut (*slot).#member` is properly aligned.
428                 // - `make_field_check` prevents `#member` from being used twice, therefore
429                 //   `(*slot).#member` is exclusively accessed and has not been initialized.
430                 (unsafe {
431                     ::pin_init::__internal::Slot::<::pin_init::__internal::Unpinned, _>::new(
432                         &raw mut (*slot).#member
433                     )
434                 })
435             }
436         };
437 
438         // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
439         let guard = format_ident!("__{ident}_guard", span = span);
440         let full_span = kind.span().resolved_at(Span::mixed_site());
441 
442         let init = match kind {
443             InitializerKind::Value { value, .. } => {
444                 let (colon_span, value) = value
445                     .as_ref()
446                     .map(|(colon_token, value)| (colon_token.span(), quote!(#value)))
447                     .unwrap_or_else(|| (member.span(), quote!(#member)));
448 
449                 // Use `:` as the span of the method name, so the type requirement appears to come
450                 // from `:`.
451                 let write =
452                     format_ident!("write", span = colon_span.resolved_at(Span::mixed_site()));
453 
454                 quote_spanned! { full_span =>
455                     #(#attrs)*
456                     let mut #guard = #slot.#write(#value);
457                 }
458             }
459             InitializerKind::Init {
460                 value,
461                 left_arrow_token,
462                 ..
463             } => {
464                 // Use `<-` as the span of the method name, so the trait bound appears to come from
465                 // `<-`.
466                 let init = format_ident!(
467                     "init",
468                     span = left_arrow_token.span().resolved_at(Span::mixed_site())
469                 );
470 
471                 quote_spanned! { full_span =>
472                     #(#attrs)*
473                     let mut #guard = #slot.#init(#value)?;
474                 }
475             }
476             InitializerKind::Code { .. } => unreachable!(),
477         };
478 
479         // A tuple field has no name that could be bound here (the `_0` identifiers are considered
480         // implementation detail and not user-facing).
481         let let_binding_method = if !dropck {
482             format_ident!("let_binding", span = span)
483         } else {
484             format_ident!("let_binding_in_dropck", span = span)
485         };
486         let binding = match member {
487             Member::Named(ident) => quote_spanned! { span =>
488                 #(#cfgs)*
489                 // Allow `non_snake_case` since the same warning is going to be reported for the
490                 // struct field.
491                 #[allow(unused_variables, non_snake_case)]
492                 // Include `mut` so that `Pin<&mut T>` bindings can be reborrowed via `.as_mut()`.
493                 let mut #ident = #guard.#let_binding_method();
494             },
495             Member::Unnamed(_) => quote!(),
496         };
497 
498         res.extend(quote! {
499             #init
500 
501             #binding
502         });
503 
504         forget_guards.push(quote_spanned! { span =>
505             #(#cfgs)*
506             ::core::mem::forget(#guard);
507         });
508     }
509 
510     forget_guards.reverse();
511 
512     quote! {
513         #res
514         // If execution reaches this point, all fields have been initialized. Therefore we can now
515         // dismiss the guards by forgetting them.
516         #(#forget_guards)*
517     }
518 }
519 
520 /// Generate the check for ensuring that every field has been initialized and aligned.
521 fn make_field_check(
522     fields: &Punctuated<InitializerField, Token![,]>,
523     init_kind: InitKind,
524     path: &Path,
525 ) -> TokenStream {
526     let align_checks: TokenStream = fields
527         .iter()
528         .filter_map(|f| {
529             let member = f.kind.member()?;
530             let span = member.span().resolved_at(Span::mixed_site());
531             let attrs = &f.attrs;
532 
533             Some(quote_spanned! {span =>
534                 // Create references to ensure that the initialized field is properly aligned.
535                 // Unaligned fields will cause the compiler to emit E0793. We do not support
536                 // unaligned fields since `Init::__init` requires an aligned pointer; the call to
537                 // `ptr::write` for value-initialization case has the same requirement.
538                 #(#attrs)*
539                 let _ = &(*slot).#member;
540             })
541         })
542         .collect();
543 
544     let fake_field_init: TokenStream = fields
545         .iter()
546         .filter_map(|f| {
547             let member = f.kind.member()?;
548             let span = member.span().resolved_at(Span::mixed_site());
549             let attrs = &f.attrs;
550 
551             Some(quote_spanned! {span =>
552                 #(#attrs)*
553                 #member: loop {},
554             })
555         })
556         .collect();
557     let zeroing_trailer = match init_kind {
558         InitKind::Normal => None,
559         InitKind::Zeroing => Some(quote! {
560             ..::core::mem::zeroed()
561         }),
562     };
563     let field_dup_checks = quote_spanned! { Span::mixed_site() =>
564         // If the zeroing trailer is not present, this checks that all fields have been
565         // mentioned exactly once. If the zeroing trailer is present, all missing fields will be
566         // zeroed, so this checks that all fields have been mentioned at most once. The use of
567         // struct initializer will still generate very natural error messages for any misuse.
568         ::core::ptr::write(slot, #path {
569             #fake_field_init
570             #zeroing_trailer
571         })
572     };
573 
574     quote_spanned! { Span::mixed_site() =>
575         #[allow(unreachable_code)]
576         // We use unreachable code to perform field checks. They're still checked by the compiler.
577         // SAFETY: this code is never executed.
578         let _ = || unsafe {
579             #align_checks
580             #field_dup_checks
581         };
582     }
583 }
584 
585 impl InitExprStruct {
586     fn parse_with_path(path: Path, input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
587         let content;
588         let brace_token = braced!(content in input);
589         let mut fields = Punctuated::new();
590         loop {
591             let lh = content.lookahead1();
592             if lh.peek(End) || lh.peek(Token![..]) {
593                 break;
594             } else if lh.peek(Ident) || lh.peek(LitInt) || lh.peek(Token![_]) || lh.peek(Token![#])
595             {
596                 fields.push_value(content.parse()?);
597                 let lh = content.lookahead1();
598                 if lh.peek(End) {
599                     break;
600                 } else if lh.peek(Token![,]) {
601                     fields.push_punct(content.parse()?);
602                 } else {
603                     return Err(lh.error());
604                 }
605             } else {
606                 return Err(lh.error());
607             }
608         }
609         let rest = content
610             .peek(Token![..])
611             .then(|| Ok::<_, syn::Error>((content.parse()?, content.parse()?)))
612             .transpose()?;
613         Ok(Self {
614             path,
615             brace_token,
616             fields,
617             rest,
618         })
619     }
620 }
621 
622 impl InitExprTuple {
623     fn parse_with_path(path: Path, input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
624         let content;
625         let paren_token = parenthesized!(content in input);
626         let mut fields = Punctuated::new();
627         while !content.is_empty() {
628             let attrs = content.call(Attribute::parse_outer)?;
629 
630             if let Some(left_arrow_token) = content.parse::<Option<Token![<-]>>()? {
631                 DiagCtxt::current(|dcx| {
632                     dcx.error(
633                         left_arrow_token,
634                         "`<-` is not supported in tuple constructor syntax; name the fields by \
635                         index instead, e.g. `Type { 0 <- initializer, 1: value }`",
636                     )
637                 });
638             }
639 
640             fields.push_value(InitTupleField {
641                 attrs,
642                 value: content.parse()?,
643             });
644             if content.is_empty() {
645                 break;
646             }
647             fields.push_punct(content.parse()?);
648         }
649         Ok(InitExprTuple {
650             path,
651             paren_token,
652             fields,
653         })
654     }
655 }
656 
657 impl Parse for Initializer {
658     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
659         let attrs = input.call(Attribute::parse_outer)?;
660         let this = input.peek(Token![&]).then(|| input.parse()).transpose()?;
661         let path = input.parse()?;
662         let kind = if input.peek(token::Brace) {
663             InitExprKind::Struct(InitExprStruct::parse_with_path(path, input)?)
664         } else if input.peek(token::Paren) {
665             InitExprKind::Tuple(InitExprTuple::parse_with_path(path, input)?)
666         } else {
667             return Err(input.error("expected curly braces or parentheses"));
668         };
669         let error = input
670             .peek(Token![?])
671             .then(|| Ok::<_, syn::Error>((input.parse()?, input.parse()?)))
672             .transpose()?;
673         let attrs = attrs
674             .into_iter()
675             .map(|a| {
676                 if a.path().is_ident("default_error") {
677                     a.parse_args::<DefaultErrorAttribute>()
678                         .map(InitializerAttribute::DefaultError)
679                 } else {
680                     Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
681                 }
682             })
683             .collect::<Result<Vec<_>, _>>()?;
684         Ok(Self {
685             attrs,
686             this,
687             kind,
688             error,
689         })
690     }
691 }
692 
693 impl Parse for DefaultErrorAttribute {
694     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
695         Ok(Self { ty: input.parse()? })
696     }
697 }
698 
699 impl Parse for This {
700     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
701         Ok(Self {
702             _and_token: input.parse()?,
703             ident: input.parse()?,
704             _in_token: input.parse()?,
705         })
706     }
707 }
708 
709 impl Parse for InitializerField {
710     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
711         let attrs = input.call(Attribute::parse_outer)?;
712         Ok(Self {
713             attrs,
714             kind: input.parse()?,
715         })
716     }
717 }
718 
719 impl Parse for InitializerKind {
720     fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
721         let lh = input.lookahead1();
722         let member = if lh.peek(Token![_]) {
723             return Ok(Self::Code {
724                 _underscore_token: input.parse()?,
725                 _colon_token: input.parse()?,
726                 block: input.parse()?,
727             });
728         } else if lh.peek(Ident) || lh.peek(LitInt) {
729             input.parse::<Member>()?
730         } else {
731             return Err(lh.error());
732         };
733 
734         let lh = input.lookahead1();
735         if lh.peek(Token![<-]) {
736             Ok(Self::Init {
737                 member,
738                 left_arrow_token: input.parse()?,
739                 value: input.parse()?,
740             })
741         } else if lh.peek(Token![:]) {
742             Ok(Self::Value {
743                 member,
744                 value: Some((input.parse()?, input.parse()?)),
745             })
746         } else if matches!(member, Member::Named(_)) && (lh.peek(Token![,]) || lh.peek(End)) {
747             // Short-hand syntax, available for named fields only.
748             Ok(Self::Value {
749                 member,
750                 value: None,
751             })
752         } else {
753             Err(lh.error())
754         }
755     }
756 }
757 
758 impl<Kind: ToTokens> ToTokens for Initializer<Kind> {
759     fn to_tokens(&self, tokens: &mut TokenStream) {
760         let Self {
761             attrs,
762             this,
763             kind,
764             error,
765         } = self;
766         tokens.append_all(attrs);
767         this.to_tokens(tokens);
768         kind.to_tokens(tokens);
769         if let Some((question, ty)) = error {
770             question.to_tokens(tokens);
771             ty.to_tokens(tokens);
772         }
773     }
774 }
775 
776 impl ToTokens for InitExprKind {
777     fn to_tokens(&self, tokens: &mut TokenStream) {
778         match self {
779             Self::Struct(init) => init.to_tokens(tokens),
780             Self::Tuple(init) => init.to_tokens(tokens),
781         }
782     }
783 }
784 
785 impl ToTokens for InitExprStruct {
786     fn to_tokens(&self, tokens: &mut TokenStream) {
787         let Self {
788             path,
789             brace_token,
790             fields,
791             rest,
792         } = self;
793         path.to_tokens(tokens);
794         brace_token.surround(tokens, |tokens| {
795             fields.to_tokens(tokens);
796             if let Some((dotdot, expr)) = rest {
797                 dotdot.to_tokens(tokens);
798                 expr.to_tokens(tokens);
799             }
800         });
801     }
802 }
803 
804 impl ToTokens for InitExprTuple {
805     fn to_tokens(&self, tokens: &mut TokenStream) {
806         let Self {
807             path,
808             paren_token,
809             fields,
810         } = self;
811         path.to_tokens(tokens);
812         paren_token.surround(tokens, |tokens| fields.to_tokens(tokens));
813     }
814 }
815 
816 impl ToTokens for InitTupleField {
817     fn to_tokens(&self, tokens: &mut TokenStream) {
818         let Self { attrs, value } = self;
819         tokens.append_all(attrs);
820         value.to_tokens(tokens);
821     }
822 }
823 
824 impl ToTokens for InitializerAttribute {
825     fn to_tokens(&self, tokens: &mut TokenStream) {
826         match self {
827             Self::DefaultError(DefaultErrorAttribute { ty }) => {
828                 quote!(#[default_error(#ty)]).to_tokens(tokens);
829             }
830         }
831     }
832 }
833 
834 impl ToTokens for This {
835     fn to_tokens(&self, tokens: &mut TokenStream) {
836         let Self {
837             _and_token,
838             ident,
839             _in_token,
840         } = self;
841         _and_token.to_tokens(tokens);
842         ident.to_tokens(tokens);
843         _in_token.to_tokens(tokens);
844     }
845 }
846 
847 impl ToTokens for InitializerField {
848     fn to_tokens(&self, tokens: &mut TokenStream) {
849         let Self { attrs, kind } = self;
850         tokens.append_all(attrs);
851         kind.to_tokens(tokens);
852     }
853 }
854 
855 impl ToTokens for InitializerKind {
856     fn to_tokens(&self, tokens: &mut TokenStream) {
857         match self {
858             Self::Value { member, value } => {
859                 member.to_tokens(tokens);
860                 if let Some((colon, expr)) = value {
861                     colon.to_tokens(tokens);
862                     expr.to_tokens(tokens);
863                 }
864             }
865             Self::Init {
866                 member,
867                 left_arrow_token,
868                 value,
869             } => {
870                 member.to_tokens(tokens);
871                 left_arrow_token.to_tokens(tokens);
872                 value.to_tokens(tokens);
873             }
874             Self::Code {
875                 _underscore_token,
876                 _colon_token,
877                 block,
878             } => {
879                 _underscore_token.to_tokens(tokens);
880                 _colon_token.to_tokens(tokens);
881                 block.to_tokens(tokens);
882             }
883         }
884     }
885 }
886