Skip to main content

pin_init_internal/
init.rs

1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3use proc_macro2::{Span, TokenStream};
4use quote::{format_ident, quote, quote_spanned, ToTokens, TokenStreamExt};
5use 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
15use crate::{
16    diagnostics::{DiagCtxt, ErrorGuaranteed},
17    util::*,
18};
19
20pub(crate) struct Initializer<Kind = InitExprKind> {
21    attrs: Vec<InitializerAttribute>,
22    this: Option<This>,
23    kind: Kind,
24    error: Option<(Token![?], Type)>,
25}
26
27pub(crate) struct InitExprStruct {
28    path: Path,
29    brace_token: token::Brace,
30    fields: Punctuated<InitializerField, Token![,]>,
31    rest: Option<(Token![..], Expr)>,
32}
33
34pub(crate) struct InitExprTuple {
35    path: Path,
36    paren_token: token::Paren,
37    fields: Punctuated<InitTupleField, Token![,]>,
38}
39
40pub(crate) enum InitExprKind {
41    Struct(InitExprStruct),
42    Tuple(InitExprTuple),
43}
44
45struct InitTupleField {
46    attrs: Vec<Attribute>,
47    value: Expr,
48}
49
50impl 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
86struct This {
87    _and_token: Token![&],
88    ident: Ident,
89    _in_token: Token![in],
90}
91
92struct InitializerField {
93    attrs: Vec<Attribute>,
94    kind: InitializerKind,
95}
96
97enum 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
114impl 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
123enum InitializerAttribute {
124    DefaultError(DefaultErrorAttribute),
125}
126
127struct DefaultErrorAttribute {
128    ty: Box<Type>,
129}
130
131pub(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
213fn 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 = init_fields(&fields, pinned);
292    let field_check = make_field_check(&fields, init_kind, &path);
293    Ok(quote_spanned! { Span::mixed_site() => {
294        // Get the data about fields from the supplied type.
295        let data = {
296            use ::pin_init::__internal::HasInitData;
297            // Can't use `<#path as #has_data_trait>::#get_data`, since the user is able to omit
298            // generics (which need to be present with that syntax).
299            #path::__init_data()
300        };
301
302        #get_pin_data
303
304        // Ensure that `data` really is of type `data` and help with type inference:
305        let init = data.__make_closure::<_, #error>(
306            move |slot| {
307                #zeroable_check
308                #this
309                #init_fields
310                #field_check
311                // SAFETY: we are the `init!` macro that is allowed to call this.
312                Ok(unsafe { ::pin_init::__internal::InitOk::new() })
313            }
314        );
315        let init = move |slot| -> ::core::result::Result<(), #error> {
316            init(slot).map(|__InitOk| ())
317        };
318        // SAFETY: TODO
319        unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }
320    }})
321}
322
323enum InitKind {
324    Normal,
325    Zeroing,
326}
327
328fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKind {
329    let Some((dotdot, expr)) = rest else {
330        return InitKind::Normal;
331    };
332    match &expr {
333        Expr::Call(ExprCall { func, args, .. }) if args.is_empty() => match &**func {
334            Expr::Path(ExprPath {
335                attrs,
336                qself: None,
337                path:
338                    Path {
339                        leading_colon: None,
340                        segments,
341                    },
342            }) if attrs.is_empty()
343                && segments.len() == 2
344                && segments[0].ident == "Zeroable"
345                && segments[0].arguments.is_none()
346                && segments[1].ident == "init_zeroed"
347                && segments[1].arguments.is_none() =>
348            {
349                return InitKind::Zeroing;
350            }
351            _ => {}
352        },
353        _ => {}
354    }
355    dcx.error(
356        dotdot.span().join(expr.span()).unwrap_or(expr.span()),
357        "expected nothing or `..Zeroable::init_zeroed()`.",
358    );
359    InitKind::Normal
360}
361
362/// Generate the code that initializes the fields of the struct using the initializers in `field`.
363fn init_fields(fields: &Punctuated<InitializerField, Token![,]>, pinned: bool) -> TokenStream {
364    let mut forget_guards = vec![];
365    let mut res = TokenStream::new();
366    for InitializerField { attrs, kind } in fields {
367        let cfgs = {
368            let mut cfgs = attrs.clone();
369            cfgs.retain(|attr| attr.path().is_ident("cfg"));
370            cfgs
371        };
372
373        let member = match kind {
374            InitializerKind::Value { member, .. } => member,
375            InitializerKind::Init { member, .. } => member,
376            InitializerKind::Code { block, .. } => {
377                let stmt = &block.stmts;
378                res.extend(quote! {
379                    #(#attrs)*
380                    {
381                        #(#stmt)*
382                    }
383                });
384                continue;
385            }
386        };
387        let ident = member.as_ident();
388        let span = Span::mixed_site().located_at(ident.span());
389
390        let slot = if pinned {
391            quote_spanned! { span =>
392                // SAFETY:
393                // - `slot` is valid and properly aligned.
394                // - `make_field_check` checks that `&raw mut (*slot).#member` is properly aligned.
395                // - `make_field_check` prevents `#member` from being used twice, therefore
396                //   `(*slot).#member` is exclusively accessed and has not been initialized.
397                (unsafe { data.#ident(slot) })
398            }
399        } else {
400            quote_spanned! { span =>
401                // For `init!()` macro, everything is unpinned.
402                // SAFETY:
403                // - `&raw mut (*slot).#member` is valid.
404                // - `make_field_check` checks that `&raw mut (*slot).#member` is properly aligned.
405                // - `make_field_check` prevents `#member` from being used twice, therefore
406                //   `(*slot).#member` is exclusively accessed and has not been initialized.
407                (unsafe {
408                    ::pin_init::__internal::Slot::<::pin_init::__internal::Unpinned, _>::new(
409                        &raw mut (*slot).#member
410                    )
411                })
412            }
413        };
414
415        // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
416        let guard = format_ident!("__{ident}_guard", span = span);
417        let full_span = kind.span().resolved_at(Span::mixed_site());
418
419        let init = match kind {
420            InitializerKind::Value { value, .. } => {
421                let (colon_span, value) = value
422                    .as_ref()
423                    .map(|(colon_token, value)| (colon_token.span(), quote!(#value)))
424                    .unwrap_or_else(|| (member.span(), quote!(#member)));
425
426                // Use `:` as the span of the method name, so the type requirement appears to come
427                // from `:`.
428                let write =
429                    format_ident!("write", span = colon_span.resolved_at(Span::mixed_site()));
430
431                quote_spanned! { full_span =>
432                    #(#attrs)*
433                    let mut #guard = #slot.#write(#value);
434                }
435            }
436            InitializerKind::Init {
437                value,
438                left_arrow_token,
439                ..
440            } => {
441                // Use `<-` as the span of the method name, so the trait bound appears to come from
442                // `<-`.
443                let init = format_ident!(
444                    "init",
445                    span = left_arrow_token.span().resolved_at(Span::mixed_site())
446                );
447
448                quote_spanned! { full_span =>
449                    #(#attrs)*
450                    let mut #guard = #slot.#init(#value)?;
451                }
452            }
453            InitializerKind::Code { .. } => unreachable!(),
454        };
455
456        // A tuple field has no name that could be bound here (the `_0` identifiers are considered
457        // implementation detail and not user-facing).
458        let binding = match member {
459            Member::Named(ident) => quote_spanned! { span =>
460                #(#cfgs)*
461                // Allow `non_snake_case` since the same warning is going to be reported for the
462                // struct field.
463                #[allow(unused_variables, non_snake_case)]
464                // Include `mut` so that `Pin<&mut T>` bindings can be reborrowed via `.as_mut()`.
465                let mut #ident = #guard.let_binding();
466            },
467            Member::Unnamed(_) => quote!(),
468        };
469
470        res.extend(quote! {
471            #init
472
473            #binding
474        });
475
476        forget_guards.push(quote_spanned! { span =>
477            #(#cfgs)*
478            ::core::mem::forget(#guard);
479        });
480    }
481
482    forget_guards.reverse();
483
484    quote! {
485        #res
486        // If execution reaches this point, all fields have been initialized. Therefore we can now
487        // dismiss the guards by forgetting them.
488        #(#forget_guards)*
489    }
490}
491
492/// Generate the check for ensuring that every field has been initialized and aligned.
493fn make_field_check(
494    fields: &Punctuated<InitializerField, Token![,]>,
495    init_kind: InitKind,
496    path: &Path,
497) -> TokenStream {
498    let align_checks: TokenStream = fields
499        .iter()
500        .filter_map(|f| {
501            let member = f.kind.member()?;
502            let span = member.span().resolved_at(Span::mixed_site());
503            let attrs = &f.attrs;
504
505            Some(quote_spanned! {span =>
506                // Create references to ensure that the initialized field is properly aligned.
507                // Unaligned fields will cause the compiler to emit E0793. We do not support
508                // unaligned fields since `Init::__init` requires an aligned pointer; the call to
509                // `ptr::write` for value-initialization case has the same requirement.
510                #(#attrs)*
511                let _ = &(*slot).#member;
512            })
513        })
514        .collect();
515
516    let fake_field_init: TokenStream = fields
517        .iter()
518        .filter_map(|f| {
519            let member = f.kind.member()?;
520            let span = member.span().resolved_at(Span::mixed_site());
521            let attrs = &f.attrs;
522
523            Some(quote_spanned! {span =>
524                #(#attrs)*
525                #member: loop {},
526            })
527        })
528        .collect();
529    let zeroing_trailer = match init_kind {
530        InitKind::Normal => None,
531        InitKind::Zeroing => Some(quote! {
532            ..::core::mem::zeroed()
533        }),
534    };
535    let field_dup_checks = quote_spanned! { Span::mixed_site() =>
536        // If the zeroing trailer is not present, this checks that all fields have been
537        // mentioned exactly once. If the zeroing trailer is present, all missing fields will be
538        // zeroed, so this checks that all fields have been mentioned at most once. The use of
539        // struct initializer will still generate very natural error messages for any misuse.
540        ::core::ptr::write(slot, #path {
541            #fake_field_init
542            #zeroing_trailer
543        })
544    };
545
546    quote_spanned! { Span::mixed_site() =>
547        #[allow(unreachable_code)]
548        // We use unreachable code to perform field checks. They're still checked by the compiler.
549        // SAFETY: this code is never executed.
550        let _ = || unsafe {
551            #align_checks
552            #field_dup_checks
553        };
554    }
555}
556
557impl InitExprStruct {
558    fn parse_with_path(path: Path, input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
559        let content;
560        let brace_token = braced!(content in input);
561        let mut fields = Punctuated::new();
562        loop {
563            let lh = content.lookahead1();
564            if lh.peek(End) || lh.peek(Token![..]) {
565                break;
566            } else if lh.peek(Ident) || lh.peek(LitInt) || lh.peek(Token![_]) || lh.peek(Token![#])
567            {
568                fields.push_value(content.parse()?);
569                let lh = content.lookahead1();
570                if lh.peek(End) {
571                    break;
572                } else if lh.peek(Token![,]) {
573                    fields.push_punct(content.parse()?);
574                } else {
575                    return Err(lh.error());
576                }
577            } else {
578                return Err(lh.error());
579            }
580        }
581        let rest = content
582            .peek(Token![..])
583            .then(|| Ok::<_, syn::Error>((content.parse()?, content.parse()?)))
584            .transpose()?;
585        Ok(Self {
586            path,
587            brace_token,
588            fields,
589            rest,
590        })
591    }
592}
593
594impl InitExprTuple {
595    fn parse_with_path(path: Path, input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
596        let content;
597        let paren_token = parenthesized!(content in input);
598        let mut fields = Punctuated::new();
599        while !content.is_empty() {
600            let attrs = content.call(Attribute::parse_outer)?;
601
602            if let Some(left_arrow_token) = content.parse::<Option<Token![<-]>>()? {
603                DiagCtxt::current(|dcx| {
604                    dcx.error(
605                        left_arrow_token,
606                        "`<-` is not supported in tuple constructor syntax; name the fields by \
607                        index instead, e.g. `Type { 0 <- initializer, 1: value }`",
608                    )
609                });
610            }
611
612            fields.push_value(InitTupleField {
613                attrs,
614                value: content.parse()?,
615            });
616            if content.is_empty() {
617                break;
618            }
619            fields.push_punct(content.parse()?);
620        }
621        Ok(InitExprTuple {
622            path,
623            paren_token,
624            fields,
625        })
626    }
627}
628
629impl Parse for Initializer {
630    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
631        let attrs = input.call(Attribute::parse_outer)?;
632        let this = input.peek(Token![&]).then(|| input.parse()).transpose()?;
633        let path = input.parse()?;
634        let kind = if input.peek(token::Brace) {
635            InitExprKind::Struct(InitExprStruct::parse_with_path(path, input)?)
636        } else if input.peek(token::Paren) {
637            InitExprKind::Tuple(InitExprTuple::parse_with_path(path, input)?)
638        } else {
639            return Err(input.error("expected curly braces or parentheses"));
640        };
641        let error = input
642            .peek(Token![?])
643            .then(|| Ok::<_, syn::Error>((input.parse()?, input.parse()?)))
644            .transpose()?;
645        let attrs = attrs
646            .into_iter()
647            .map(|a| {
648                if a.path().is_ident("default_error") {
649                    a.parse_args::<DefaultErrorAttribute>()
650                        .map(InitializerAttribute::DefaultError)
651                } else {
652                    Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
653                }
654            })
655            .collect::<Result<Vec<_>, _>>()?;
656        Ok(Self {
657            attrs,
658            this,
659            kind,
660            error,
661        })
662    }
663}
664
665impl Parse for DefaultErrorAttribute {
666    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
667        Ok(Self { ty: input.parse()? })
668    }
669}
670
671impl Parse for This {
672    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
673        Ok(Self {
674            _and_token: input.parse()?,
675            ident: input.parse()?,
676            _in_token: input.parse()?,
677        })
678    }
679}
680
681impl Parse for InitializerField {
682    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
683        let attrs = input.call(Attribute::parse_outer)?;
684        Ok(Self {
685            attrs,
686            kind: input.parse()?,
687        })
688    }
689}
690
691impl Parse for InitializerKind {
692    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
693        let lh = input.lookahead1();
694        let member = if lh.peek(Token![_]) {
695            return Ok(Self::Code {
696                _underscore_token: input.parse()?,
697                _colon_token: input.parse()?,
698                block: input.parse()?,
699            });
700        } else if lh.peek(Ident) || lh.peek(LitInt) {
701            input.parse::<Member>()?
702        } else {
703            return Err(lh.error());
704        };
705
706        let lh = input.lookahead1();
707        if lh.peek(Token![<-]) {
708            Ok(Self::Init {
709                member,
710                left_arrow_token: input.parse()?,
711                value: input.parse()?,
712            })
713        } else if lh.peek(Token![:]) {
714            Ok(Self::Value {
715                member,
716                value: Some((input.parse()?, input.parse()?)),
717            })
718        } else if matches!(member, Member::Named(_)) && (lh.peek(Token![,]) || lh.peek(End)) {
719            // Short-hand syntax, available for named fields only.
720            Ok(Self::Value {
721                member,
722                value: None,
723            })
724        } else {
725            Err(lh.error())
726        }
727    }
728}
729
730impl<Kind: ToTokens> ToTokens for Initializer<Kind> {
731    fn to_tokens(&self, tokens: &mut TokenStream) {
732        let Self {
733            attrs,
734            this,
735            kind,
736            error,
737        } = self;
738        tokens.append_all(attrs);
739        this.to_tokens(tokens);
740        kind.to_tokens(tokens);
741        if let Some((question, ty)) = error {
742            question.to_tokens(tokens);
743            ty.to_tokens(tokens);
744        }
745    }
746}
747
748impl ToTokens for InitExprKind {
749    fn to_tokens(&self, tokens: &mut TokenStream) {
750        match self {
751            Self::Struct(init) => init.to_tokens(tokens),
752            Self::Tuple(init) => init.to_tokens(tokens),
753        }
754    }
755}
756
757impl ToTokens for InitExprStruct {
758    fn to_tokens(&self, tokens: &mut TokenStream) {
759        let Self {
760            path,
761            brace_token,
762            fields,
763            rest,
764        } = self;
765        path.to_tokens(tokens);
766        brace_token.surround(tokens, |tokens| {
767            fields.to_tokens(tokens);
768            if let Some((dotdot, expr)) = rest {
769                dotdot.to_tokens(tokens);
770                expr.to_tokens(tokens);
771            }
772        });
773    }
774}
775
776impl ToTokens for InitExprTuple {
777    fn to_tokens(&self, tokens: &mut TokenStream) {
778        let Self {
779            path,
780            paren_token,
781            fields,
782        } = self;
783        path.to_tokens(tokens);
784        paren_token.surround(tokens, |tokens| fields.to_tokens(tokens));
785    }
786}
787
788impl ToTokens for InitTupleField {
789    fn to_tokens(&self, tokens: &mut TokenStream) {
790        let Self { attrs, value } = self;
791        tokens.append_all(attrs);
792        value.to_tokens(tokens);
793    }
794}
795
796impl ToTokens for InitializerAttribute {
797    fn to_tokens(&self, tokens: &mut TokenStream) {
798        match self {
799            Self::DefaultError(DefaultErrorAttribute { ty }) => {
800                quote!(#[default_error(#ty)]).to_tokens(tokens);
801            }
802        }
803    }
804}
805
806impl ToTokens for This {
807    fn to_tokens(&self, tokens: &mut TokenStream) {
808        let Self {
809            _and_token,
810            ident,
811            _in_token,
812        } = self;
813        _and_token.to_tokens(tokens);
814        ident.to_tokens(tokens);
815        _in_token.to_tokens(tokens);
816    }
817}
818
819impl ToTokens for InitializerField {
820    fn to_tokens(&self, tokens: &mut TokenStream) {
821        let Self { attrs, kind } = self;
822        tokens.append_all(attrs);
823        kind.to_tokens(tokens);
824    }
825}
826
827impl ToTokens for InitializerKind {
828    fn to_tokens(&self, tokens: &mut TokenStream) {
829        match self {
830            Self::Value { member, value } => {
831                member.to_tokens(tokens);
832                if let Some((colon, expr)) = value {
833                    colon.to_tokens(tokens);
834                    expr.to_tokens(tokens);
835                }
836            }
837            Self::Init {
838                member,
839                left_arrow_token,
840                value,
841            } => {
842                member.to_tokens(tokens);
843                left_arrow_token.to_tokens(tokens);
844                value.to_tokens(tokens);
845            }
846            Self::Code {
847                _underscore_token,
848                _colon_token,
849                block,
850            } => {
851                _underscore_token.to_tokens(tokens);
852                _colon_token.to_tokens(tokens);
853                block.to_tokens(tokens);
854            }
855        }
856    }
857}