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, 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