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 = 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
337enum InitKind {
338    Normal,
339    Zeroing,
340}
341
342fn 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`.
377fn 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.
521fn 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
585impl 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
622impl 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
657impl 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
693impl Parse for DefaultErrorAttribute {
694    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
695        Ok(Self { ty: input.parse()? })
696    }
697}
698
699impl 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
709impl 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
719impl 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
758impl<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
776impl 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
785impl 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
804impl 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
816impl 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
824impl 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
834impl 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
847impl 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
855impl 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}