1 use crate::attr::Attribute; 2 use crate::expr::Expr; 3 use crate::ident::Ident; 4 use crate::lifetime::Lifetime; 5 use crate::path::Path; 6 use crate::punctuated::{Iter, IterMut, Punctuated}; 7 use crate::token; 8 use crate::ty::Type; 9 use proc_macro2::TokenStream; 10 #[cfg(all(feature = "printing", feature = "extra-traits"))] 11 use std::fmt::{self, Debug}; 12 #[cfg(all(feature = "printing", feature = "extra-traits"))] 13 use std::hash::{Hash, Hasher}; 14 15 ast_struct! { 16 /// Lifetimes and type parameters attached to a declaration of a function, 17 /// enum, trait, etc. 18 /// 19 /// This struct represents two distinct optional syntactic elements, 20 /// [generic parameters] and [where clause]. In some locations of the 21 /// grammar, there may be other tokens in between these two things. 22 /// 23 /// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters 24 /// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses 25 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 26 pub struct Generics { 27 pub lt_token: Option<Token![<]>, 28 pub params: Punctuated<GenericParam, Token![,]>, 29 pub gt_token: Option<Token![>]>, 30 pub where_clause: Option<WhereClause>, 31 } 32 } 33 34 ast_enum_of_structs! { 35 /// A generic type parameter, lifetime, or const generic: `T: Into<String>`, 36 /// `'a: 'b`, `const LEN: usize`. 37 /// 38 /// # Syntax tree enum 39 /// 40 /// This type is a [syntax tree enum]. 41 /// 42 /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums 43 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 44 pub enum GenericParam { 45 /// A lifetime parameter: `'a: 'b + 'c + 'd`. 46 Lifetime(LifetimeParam), 47 48 /// A generic type parameter: `T: Into<String>`. 49 Type(TypeParam), 50 51 /// A const generic parameter: `const LENGTH: usize`. 52 Const(ConstParam), 53 } 54 } 55 56 ast_struct! { 57 /// A lifetime definition: `'a: 'b + 'c + 'd`. 58 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 59 pub struct LifetimeParam { 60 pub attrs: Vec<Attribute>, 61 pub lifetime: Lifetime, 62 pub colon_token: Option<Token![:]>, 63 pub bounds: Punctuated<Lifetime, Token![+]>, 64 } 65 } 66 67 ast_struct! { 68 /// A generic type parameter: `T: Into<String>`. 69 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 70 pub struct TypeParam { 71 pub attrs: Vec<Attribute>, 72 pub ident: Ident, 73 pub colon_token: Option<Token![:]>, 74 pub bounds: Punctuated<TypeParamBound, Token![+]>, 75 pub eq_token: Option<Token![=]>, 76 pub default: Option<Type>, 77 } 78 } 79 80 ast_struct! { 81 /// A const generic parameter: `const LENGTH: usize`. 82 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 83 pub struct ConstParam { 84 pub attrs: Vec<Attribute>, 85 pub const_token: Token![const], 86 pub ident: Ident, 87 pub colon_token: Token![:], 88 pub ty: Type, 89 pub eq_token: Option<Token![=]>, 90 pub default: Option<Expr>, 91 } 92 } 93 94 impl Default for Generics { 95 fn default() -> Self { 96 Generics { 97 lt_token: None, 98 params: Punctuated::new(), 99 gt_token: None, 100 where_clause: None, 101 } 102 } 103 } 104 105 impl Generics { 106 return_impl_trait! { 107 /// Iterator over the lifetime parameters in `self.params`. 108 pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] { 109 Lifetimes(self.params.iter()) 110 } 111 } 112 113 return_impl_trait! { 114 /// Iterator over the lifetime parameters in `self.params`. 115 pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> [LifetimesMut] { 116 LifetimesMut(self.params.iter_mut()) 117 } 118 } 119 120 return_impl_trait! { 121 /// Iterator over the type parameters in `self.params`. 122 pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] { 123 TypeParams(self.params.iter()) 124 } 125 } 126 127 return_impl_trait! { 128 /// Iterator over the type parameters in `self.params`. 129 pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> [TypeParamsMut] { 130 TypeParamsMut(self.params.iter_mut()) 131 } 132 } 133 134 return_impl_trait! { 135 /// Iterator over the constant parameters in `self.params`. 136 pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] { 137 ConstParams(self.params.iter()) 138 } 139 } 140 141 return_impl_trait! { 142 /// Iterator over the constant parameters in `self.params`. 143 pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] { 144 ConstParamsMut(self.params.iter_mut()) 145 } 146 } 147 148 /// Initializes an empty `where`-clause if there is not one present already. 149 pub fn make_where_clause(&mut self) -> &mut WhereClause { 150 self.where_clause.get_or_insert_with(|| WhereClause { 151 where_token: <Token![where]>::default(), 152 predicates: Punctuated::new(), 153 }) 154 } 155 156 /// Split a type's generics into the pieces required for impl'ing a trait 157 /// for that type. 158 /// 159 /// ``` 160 /// # use proc_macro2::{Span, Ident}; 161 /// # use quote::quote; 162 /// # 163 /// # let generics: syn::Generics = Default::default(); 164 /// # let name = Ident::new("MyType", Span::call_site()); 165 /// # 166 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 167 /// quote! { 168 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { 169 /// // ... 170 /// } 171 /// } 172 /// # ; 173 /// ``` 174 #[cfg(feature = "printing")] 175 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 176 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) { 177 ( 178 ImplGenerics(self), 179 TypeGenerics(self), 180 self.where_clause.as_ref(), 181 ) 182 } 183 } 184 185 pub struct Lifetimes<'a>(Iter<'a, GenericParam>); 186 187 impl<'a> Iterator for Lifetimes<'a> { 188 type Item = &'a LifetimeParam; 189 190 fn next(&mut self) -> Option<Self::Item> { 191 if let GenericParam::Lifetime(lifetime) = self.0.next()? { 192 Some(lifetime) 193 } else { 194 self.next() 195 } 196 } 197 } 198 199 pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>); 200 201 impl<'a> Iterator for LifetimesMut<'a> { 202 type Item = &'a mut LifetimeParam; 203 204 fn next(&mut self) -> Option<Self::Item> { 205 if let GenericParam::Lifetime(lifetime) = self.0.next()? { 206 Some(lifetime) 207 } else { 208 self.next() 209 } 210 } 211 } 212 213 pub struct TypeParams<'a>(Iter<'a, GenericParam>); 214 215 impl<'a> Iterator for TypeParams<'a> { 216 type Item = &'a TypeParam; 217 218 fn next(&mut self) -> Option<Self::Item> { 219 if let GenericParam::Type(type_param) = self.0.next()? { 220 Some(type_param) 221 } else { 222 self.next() 223 } 224 } 225 } 226 227 pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>); 228 229 impl<'a> Iterator for TypeParamsMut<'a> { 230 type Item = &'a mut TypeParam; 231 232 fn next(&mut self) -> Option<Self::Item> { 233 if let GenericParam::Type(type_param) = self.0.next()? { 234 Some(type_param) 235 } else { 236 self.next() 237 } 238 } 239 } 240 241 pub struct ConstParams<'a>(Iter<'a, GenericParam>); 242 243 impl<'a> Iterator for ConstParams<'a> { 244 type Item = &'a ConstParam; 245 246 fn next(&mut self) -> Option<Self::Item> { 247 if let GenericParam::Const(const_param) = self.0.next()? { 248 Some(const_param) 249 } else { 250 self.next() 251 } 252 } 253 } 254 255 pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>); 256 257 impl<'a> Iterator for ConstParamsMut<'a> { 258 type Item = &'a mut ConstParam; 259 260 fn next(&mut self) -> Option<Self::Item> { 261 if let GenericParam::Const(const_param) = self.0.next()? { 262 Some(const_param) 263 } else { 264 self.next() 265 } 266 } 267 } 268 269 /// Returned by `Generics::split_for_impl`. 270 #[cfg(feature = "printing")] 271 #[cfg_attr( 272 docsrs, 273 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 274 )] 275 pub struct ImplGenerics<'a>(&'a Generics); 276 277 /// Returned by `Generics::split_for_impl`. 278 #[cfg(feature = "printing")] 279 #[cfg_attr( 280 docsrs, 281 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 282 )] 283 pub struct TypeGenerics<'a>(&'a Generics); 284 285 /// Returned by `TypeGenerics::as_turbofish`. 286 #[cfg(feature = "printing")] 287 #[cfg_attr( 288 docsrs, 289 doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) 290 )] 291 pub struct Turbofish<'a>(&'a Generics); 292 293 #[cfg(feature = "printing")] 294 macro_rules! generics_wrapper_impls { 295 ($ty:ident) => { 296 #[cfg(feature = "clone-impls")] 297 #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] 298 impl<'a> Clone for $ty<'a> { 299 fn clone(&self) -> Self { 300 $ty(self.0) 301 } 302 } 303 304 #[cfg(feature = "extra-traits")] 305 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] 306 impl<'a> Debug for $ty<'a> { 307 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 308 formatter 309 .debug_tuple(stringify!($ty)) 310 .field(self.0) 311 .finish() 312 } 313 } 314 315 #[cfg(feature = "extra-traits")] 316 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] 317 impl<'a> Eq for $ty<'a> {} 318 319 #[cfg(feature = "extra-traits")] 320 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] 321 impl<'a> PartialEq for $ty<'a> { 322 fn eq(&self, other: &Self) -> bool { 323 self.0 == other.0 324 } 325 } 326 327 #[cfg(feature = "extra-traits")] 328 #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] 329 impl<'a> Hash for $ty<'a> { 330 fn hash<H: Hasher>(&self, state: &mut H) { 331 self.0.hash(state); 332 } 333 } 334 }; 335 } 336 337 #[cfg(feature = "printing")] 338 generics_wrapper_impls!(ImplGenerics); 339 #[cfg(feature = "printing")] 340 generics_wrapper_impls!(TypeGenerics); 341 #[cfg(feature = "printing")] 342 generics_wrapper_impls!(Turbofish); 343 344 #[cfg(feature = "printing")] 345 impl<'a> TypeGenerics<'a> { 346 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`. 347 pub fn as_turbofish(&self) -> Turbofish<'a> { 348 Turbofish(self.0) 349 } 350 } 351 352 ast_struct! { 353 /// A set of bound lifetimes: `for<'a, 'b, 'c>`. 354 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 355 pub struct BoundLifetimes { 356 pub for_token: Token![for], 357 pub lt_token: Token![<], 358 pub lifetimes: Punctuated<GenericParam, Token![,]>, 359 pub gt_token: Token![>], 360 } 361 } 362 363 impl Default for BoundLifetimes { 364 fn default() -> Self { 365 BoundLifetimes { 366 for_token: Default::default(), 367 lt_token: Default::default(), 368 lifetimes: Punctuated::new(), 369 gt_token: Default::default(), 370 } 371 } 372 } 373 374 impl LifetimeParam { 375 pub fn new(lifetime: Lifetime) -> Self { 376 LifetimeParam { 377 attrs: Vec::new(), 378 lifetime, 379 colon_token: None, 380 bounds: Punctuated::new(), 381 } 382 } 383 } 384 385 impl From<Ident> for TypeParam { 386 fn from(ident: Ident) -> Self { 387 TypeParam { 388 attrs: vec![], 389 ident, 390 colon_token: None, 391 bounds: Punctuated::new(), 392 eq_token: None, 393 default: None, 394 } 395 } 396 } 397 398 ast_enum_of_structs! { 399 /// A trait or lifetime used as a bound on a type parameter. 400 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 401 #[non_exhaustive] 402 pub enum TypeParamBound { 403 Trait(TraitBound), 404 Lifetime(Lifetime), 405 PreciseCapture(PreciseCapture), 406 Verbatim(TokenStream), 407 } 408 } 409 410 ast_struct! { 411 /// A trait used as a bound on a type parameter. 412 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 413 pub struct TraitBound { 414 pub paren_token: Option<token::Paren>, 415 pub modifier: TraitBoundModifier, 416 /// The `for<'a>` in `for<'a> Foo<&'a T>` 417 pub lifetimes: Option<BoundLifetimes>, 418 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>` 419 pub path: Path, 420 } 421 } 422 423 ast_enum! { 424 /// A modifier on a trait bound, currently only used for the `?` in 425 /// `?Sized`. 426 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 427 pub enum TraitBoundModifier { 428 None, 429 Maybe(Token![?]), 430 } 431 } 432 433 ast_struct! { 434 /// Precise capturing bound: the 'use<…>' in `impl Trait + 435 /// use<'a, T>`. 436 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 437 pub struct PreciseCapture #full { 438 pub use_token: Token![use], 439 pub lt_token: Token![<], 440 pub params: Punctuated<CapturedParam, Token![,]>, 441 pub gt_token: Token![>], 442 } 443 } 444 445 #[cfg(feature = "full")] 446 ast_enum! { 447 /// Single parameter in a precise capturing bound. 448 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 449 #[non_exhaustive] 450 pub enum CapturedParam { 451 /// A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl 452 /// Trait + use<'a>`. 453 Lifetime(Lifetime), 454 /// A type parameter or const generic parameter in precise capturing 455 /// bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() -> 456 /// impl Trait + use<K>`. 457 Ident(Ident), 458 } 459 } 460 461 ast_struct! { 462 /// A `where` clause in a definition: `where T: Deserialize<'de>, D: 463 /// 'static`. 464 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 465 pub struct WhereClause { 466 pub where_token: Token![where], 467 pub predicates: Punctuated<WherePredicate, Token![,]>, 468 } 469 } 470 471 ast_enum_of_structs! { 472 /// A single predicate in a `where` clause: `T: Deserialize<'de>`. 473 /// 474 /// # Syntax tree enum 475 /// 476 /// This type is a [syntax tree enum]. 477 /// 478 /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums 479 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 480 #[non_exhaustive] 481 pub enum WherePredicate { 482 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. 483 Lifetime(PredicateLifetime), 484 485 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. 486 Type(PredicateType), 487 } 488 } 489 490 ast_struct! { 491 /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. 492 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 493 pub struct PredicateLifetime { 494 pub lifetime: Lifetime, 495 pub colon_token: Token![:], 496 pub bounds: Punctuated<Lifetime, Token![+]>, 497 } 498 } 499 500 ast_struct! { 501 /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. 502 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 503 pub struct PredicateType { 504 /// Any lifetimes from a `for` binding 505 pub lifetimes: Option<BoundLifetimes>, 506 /// The type being bounded 507 pub bounded_ty: Type, 508 pub colon_token: Token![:], 509 /// Trait and lifetime bounds (`Clone+Send+'static`) 510 pub bounds: Punctuated<TypeParamBound, Token![+]>, 511 } 512 } 513 514 #[cfg(feature = "parsing")] 515 pub(crate) mod parsing { 516 use crate::attr::Attribute; 517 #[cfg(feature = "full")] 518 use crate::error; 519 use crate::error::{Error, Result}; 520 use crate::ext::IdentExt as _; 521 use crate::generics::{ 522 BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime, 523 PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause, 524 WherePredicate, 525 }; 526 #[cfg(feature = "full")] 527 use crate::generics::{CapturedParam, PreciseCapture}; 528 use crate::ident::Ident; 529 use crate::lifetime::Lifetime; 530 use crate::parse::{Parse, ParseStream}; 531 use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments}; 532 use crate::punctuated::Punctuated; 533 use crate::token; 534 use crate::ty::Type; 535 use crate::verbatim; 536 537 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 538 impl Parse for Generics { 539 fn parse(input: ParseStream) -> Result<Self> { 540 if !input.peek(Token![<]) { 541 return Ok(Generics::default()); 542 } 543 544 let lt_token: Token![<] = input.parse()?; 545 546 let mut params = Punctuated::new(); 547 loop { 548 if input.peek(Token![>]) { 549 break; 550 } 551 552 let attrs = input.call(Attribute::parse_outer)?; 553 let lookahead = input.lookahead1(); 554 if lookahead.peek(Lifetime) { 555 params.push_value(GenericParam::Lifetime(LifetimeParam { 556 attrs, 557 ..input.parse()? 558 })); 559 } else if lookahead.peek(Ident) { 560 params.push_value(GenericParam::Type(TypeParam { 561 attrs, 562 ..input.parse()? 563 })); 564 } else if lookahead.peek(Token![const]) { 565 params.push_value(GenericParam::Const(ConstParam { 566 attrs, 567 ..input.parse()? 568 })); 569 } else if input.peek(Token![_]) { 570 params.push_value(GenericParam::Type(TypeParam { 571 attrs, 572 ident: input.call(Ident::parse_any)?, 573 colon_token: None, 574 bounds: Punctuated::new(), 575 eq_token: None, 576 default: None, 577 })); 578 } else { 579 return Err(lookahead.error()); 580 } 581 582 if input.peek(Token![>]) { 583 break; 584 } 585 let punct = input.parse()?; 586 params.push_punct(punct); 587 } 588 589 let gt_token: Token![>] = input.parse()?; 590 591 Ok(Generics { 592 lt_token: Some(lt_token), 593 params, 594 gt_token: Some(gt_token), 595 where_clause: None, 596 }) 597 } 598 } 599 600 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 601 impl Parse for GenericParam { 602 fn parse(input: ParseStream) -> Result<Self> { 603 let attrs = input.call(Attribute::parse_outer)?; 604 605 let lookahead = input.lookahead1(); 606 if lookahead.peek(Ident) { 607 Ok(GenericParam::Type(TypeParam { 608 attrs, 609 ..input.parse()? 610 })) 611 } else if lookahead.peek(Lifetime) { 612 Ok(GenericParam::Lifetime(LifetimeParam { 613 attrs, 614 ..input.parse()? 615 })) 616 } else if lookahead.peek(Token![const]) { 617 Ok(GenericParam::Const(ConstParam { 618 attrs, 619 ..input.parse()? 620 })) 621 } else { 622 Err(lookahead.error()) 623 } 624 } 625 } 626 627 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 628 impl Parse for LifetimeParam { 629 fn parse(input: ParseStream) -> Result<Self> { 630 let has_colon; 631 Ok(LifetimeParam { 632 attrs: input.call(Attribute::parse_outer)?, 633 lifetime: input.parse()?, 634 colon_token: { 635 if input.peek(Token![:]) { 636 has_colon = true; 637 Some(input.parse()?) 638 } else { 639 has_colon = false; 640 None 641 } 642 }, 643 bounds: { 644 let mut bounds = Punctuated::new(); 645 if has_colon { 646 loop { 647 if input.peek(Token![,]) || input.peek(Token![>]) { 648 break; 649 } 650 let value = input.parse()?; 651 bounds.push_value(value); 652 if !input.peek(Token![+]) { 653 break; 654 } 655 let punct = input.parse()?; 656 bounds.push_punct(punct); 657 } 658 } 659 bounds 660 }, 661 }) 662 } 663 } 664 665 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 666 impl Parse for BoundLifetimes { 667 fn parse(input: ParseStream) -> Result<Self> { 668 Ok(BoundLifetimes { 669 for_token: input.parse()?, 670 lt_token: input.parse()?, 671 lifetimes: { 672 let mut lifetimes = Punctuated::new(); 673 while !input.peek(Token![>]) { 674 lifetimes.push_value(input.parse()?); 675 if input.peek(Token![>]) { 676 break; 677 } 678 lifetimes.push_punct(input.parse()?); 679 } 680 lifetimes 681 }, 682 gt_token: input.parse()?, 683 }) 684 } 685 } 686 687 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 688 impl Parse for Option<BoundLifetimes> { 689 fn parse(input: ParseStream) -> Result<Self> { 690 if input.peek(Token![for]) { 691 input.parse().map(Some) 692 } else { 693 Ok(None) 694 } 695 } 696 } 697 698 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 699 impl Parse for TypeParam { 700 fn parse(input: ParseStream) -> Result<Self> { 701 let attrs = input.call(Attribute::parse_outer)?; 702 let ident: Ident = input.parse()?; 703 let colon_token: Option<Token![:]> = input.parse()?; 704 705 let mut bounds = Punctuated::new(); 706 if colon_token.is_some() { 707 loop { 708 if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) { 709 break; 710 } 711 bounds.push_value({ 712 let allow_precise_capture = false; 713 let allow_const = true; 714 TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? 715 }); 716 if !input.peek(Token![+]) { 717 break; 718 } 719 let punct: Token![+] = input.parse()?; 720 bounds.push_punct(punct); 721 } 722 } 723 724 let eq_token: Option<Token![=]> = input.parse()?; 725 let default = if eq_token.is_some() { 726 Some(input.parse::<Type>()?) 727 } else { 728 None 729 }; 730 731 Ok(TypeParam { 732 attrs, 733 ident, 734 colon_token, 735 bounds, 736 eq_token, 737 default, 738 }) 739 } 740 } 741 742 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 743 impl Parse for TypeParamBound { 744 fn parse(input: ParseStream) -> Result<Self> { 745 let allow_precise_capture = true; 746 let allow_const = true; 747 Self::parse_single(input, allow_precise_capture, allow_const) 748 } 749 } 750 751 impl TypeParamBound { 752 pub(crate) fn parse_single( 753 input: ParseStream, 754 #[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool, 755 allow_const: bool, 756 ) -> Result<Self> { 757 if input.peek(Lifetime) { 758 return input.parse().map(TypeParamBound::Lifetime); 759 } 760 761 #[cfg(feature = "full")] 762 { 763 if input.peek(Token![use]) { 764 let precise_capture: PreciseCapture = input.parse()?; 765 return if allow_precise_capture { 766 Ok(TypeParamBound::PreciseCapture(precise_capture)) 767 } else { 768 let msg = "`use<...>` precise capturing syntax is not allowed here"; 769 Err(error::new2( 770 precise_capture.use_token.span, 771 precise_capture.gt_token.span, 772 msg, 773 )) 774 }; 775 } 776 } 777 778 let begin = input.fork(); 779 780 let content; 781 let (paren_token, content) = if input.peek(token::Paren) { 782 (Some(parenthesized!(content in input)), &content) 783 } else { 784 (None, input) 785 }; 786 787 if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? { 788 bound.paren_token = paren_token; 789 Ok(TypeParamBound::Trait(bound)) 790 } else { 791 Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input))) 792 } 793 } 794 795 pub(crate) fn parse_multiple( 796 input: ParseStream, 797 allow_plus: bool, 798 allow_precise_capture: bool, 799 allow_const: bool, 800 ) -> Result<Punctuated<Self, Token![+]>> { 801 let mut bounds = Punctuated::new(); 802 loop { 803 let bound = Self::parse_single(input, allow_precise_capture, allow_const)?; 804 bounds.push_value(bound); 805 if !(allow_plus && input.peek(Token![+])) { 806 break; 807 } 808 bounds.push_punct(input.parse()?); 809 if !(input.peek(Ident::peek_any) 810 || input.peek(Token![::]) 811 || input.peek(Token![?]) 812 || input.peek(Lifetime) 813 || input.peek(token::Paren) 814 || (allow_const && (input.peek(token::Bracket) || input.peek(Token![const])))) 815 { 816 break; 817 } 818 } 819 Ok(bounds) 820 } 821 } 822 823 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 824 impl Parse for TraitBound { 825 fn parse(input: ParseStream) -> Result<Self> { 826 let allow_const = false; 827 Self::do_parse(input, allow_const).map(Option::unwrap) 828 } 829 } 830 831 impl TraitBound { 832 fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> { 833 let mut lifetimes: Option<BoundLifetimes> = input.parse()?; 834 835 let is_conditionally_const = cfg!(feature = "full") && input.peek(token::Bracket); 836 let is_unconditionally_const = cfg!(feature = "full") && input.peek(Token![const]); 837 if is_conditionally_const { 838 let conditionally_const; 839 let bracket_token = bracketed!(conditionally_const in input); 840 conditionally_const.parse::<Token![const]>()?; 841 if !allow_const { 842 let msg = "`[const]` is not allowed here"; 843 return Err(Error::new(bracket_token.span.join(), msg)); 844 } 845 } else if is_unconditionally_const { 846 let const_token: Token![const] = input.parse()?; 847 if !allow_const { 848 let msg = "`const` is not allowed here"; 849 return Err(Error::new(const_token.span, msg)); 850 } 851 } 852 853 let modifier: TraitBoundModifier = input.parse()?; 854 if lifetimes.is_none() && matches!(modifier, TraitBoundModifier::Maybe(_)) { 855 lifetimes = input.parse()?; 856 } 857 858 let mut path: Path = input.parse()?; 859 if path.segments.last().unwrap().arguments.is_empty() 860 && (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren)) 861 { 862 input.parse::<Option<Token![::]>>()?; 863 let args: ParenthesizedGenericArguments = input.parse()?; 864 let parenthesized = PathArguments::Parenthesized(args); 865 path.segments.last_mut().unwrap().arguments = parenthesized; 866 } 867 868 if lifetimes.is_some() { 869 match modifier { 870 TraitBoundModifier::None => {} 871 TraitBoundModifier::Maybe(maybe) => { 872 let msg = "`for<...>` binder not allowed with `?` trait polarity modifier"; 873 return Err(Error::new(maybe.span, msg)); 874 } 875 } 876 } 877 878 if is_conditionally_const || is_unconditionally_const { 879 Ok(None) 880 } else { 881 Ok(Some(TraitBound { 882 paren_token: None, 883 modifier, 884 lifetimes, 885 path, 886 })) 887 } 888 } 889 } 890 891 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 892 impl Parse for TraitBoundModifier { 893 fn parse(input: ParseStream) -> Result<Self> { 894 if input.peek(Token![?]) { 895 input.parse().map(TraitBoundModifier::Maybe) 896 } else { 897 Ok(TraitBoundModifier::None) 898 } 899 } 900 } 901 902 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 903 impl Parse for ConstParam { 904 fn parse(input: ParseStream) -> Result<Self> { 905 let mut default = None; 906 Ok(ConstParam { 907 attrs: input.call(Attribute::parse_outer)?, 908 const_token: input.parse()?, 909 ident: input.parse()?, 910 colon_token: input.parse()?, 911 ty: input.parse()?, 912 eq_token: { 913 if input.peek(Token![=]) { 914 let eq_token = input.parse()?; 915 default = Some(path::parsing::const_argument(input)?); 916 Some(eq_token) 917 } else { 918 None 919 } 920 }, 921 default, 922 }) 923 } 924 } 925 926 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 927 impl Parse for WhereClause { 928 fn parse(input: ParseStream) -> Result<Self> { 929 let where_token: Token![where] = input.parse()?; 930 931 if choose_generics_over_qpath(input) { 932 return Err(input 933 .error("generic parameters on `where` clauses are reserved for future use")); 934 } 935 936 Ok(WhereClause { 937 where_token, 938 predicates: { 939 let mut predicates = Punctuated::new(); 940 loop { 941 if input.is_empty() 942 || input.peek(token::Brace) 943 || input.peek(Token![,]) 944 || input.peek(Token![;]) 945 || input.peek(Token![:]) && !input.peek(Token![::]) 946 || input.peek(Token![=]) 947 { 948 break; 949 } 950 let value = input.parse()?; 951 predicates.push_value(value); 952 if !input.peek(Token![,]) { 953 break; 954 } 955 let punct = input.parse()?; 956 predicates.push_punct(punct); 957 } 958 predicates 959 }, 960 }) 961 } 962 } 963 964 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 965 impl Parse for Option<WhereClause> { 966 fn parse(input: ParseStream) -> Result<Self> { 967 if input.peek(Token![where]) { 968 input.parse().map(Some) 969 } else { 970 Ok(None) 971 } 972 } 973 } 974 975 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 976 impl Parse for WherePredicate { 977 fn parse(input: ParseStream) -> Result<Self> { 978 if input.peek(Lifetime) && input.peek2(Token![:]) { 979 Ok(WherePredicate::Lifetime(PredicateLifetime { 980 lifetime: input.parse()?, 981 colon_token: input.parse()?, 982 bounds: { 983 let mut bounds = Punctuated::new(); 984 loop { 985 if input.is_empty() 986 || input.peek(token::Brace) 987 || input.peek(Token![,]) 988 || input.peek(Token![;]) 989 || input.peek(Token![:]) 990 || input.peek(Token![=]) 991 { 992 break; 993 } 994 let value = input.parse()?; 995 bounds.push_value(value); 996 if !input.peek(Token![+]) { 997 break; 998 } 999 let punct = input.parse()?; 1000 bounds.push_punct(punct); 1001 } 1002 bounds 1003 }, 1004 })) 1005 } else { 1006 Ok(WherePredicate::Type(PredicateType { 1007 lifetimes: input.parse()?, 1008 bounded_ty: input.parse()?, 1009 colon_token: input.parse()?, 1010 bounds: { 1011 let mut bounds = Punctuated::new(); 1012 loop { 1013 if input.is_empty() 1014 || input.peek(token::Brace) 1015 || input.peek(Token![,]) 1016 || input.peek(Token![;]) 1017 || input.peek(Token![:]) && !input.peek(Token![::]) 1018 || input.peek(Token![=]) 1019 { 1020 break; 1021 } 1022 bounds.push_value({ 1023 let allow_precise_capture = false; 1024 let allow_const = true; 1025 TypeParamBound::parse_single( 1026 input, 1027 allow_precise_capture, 1028 allow_const, 1029 )? 1030 }); 1031 if !input.peek(Token![+]) { 1032 break; 1033 } 1034 let punct = input.parse()?; 1035 bounds.push_punct(punct); 1036 } 1037 bounds 1038 }, 1039 })) 1040 } 1041 } 1042 } 1043 1044 #[cfg(feature = "full")] 1045 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 1046 impl Parse for PreciseCapture { 1047 fn parse(input: ParseStream) -> Result<Self> { 1048 let use_token: Token![use] = input.parse()?; 1049 let lt_token: Token![<] = input.parse()?; 1050 let mut params = Punctuated::new(); 1051 loop { 1052 let lookahead = input.lookahead1(); 1053 params.push_value( 1054 if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(Token![Self]) 1055 { 1056 input.parse::<CapturedParam>()? 1057 } else if lookahead.peek(Token![>]) { 1058 break; 1059 } else { 1060 return Err(lookahead.error()); 1061 }, 1062 ); 1063 let lookahead = input.lookahead1(); 1064 params.push_punct(if lookahead.peek(Token![,]) { 1065 input.parse::<Token![,]>()? 1066 } else if lookahead.peek(Token![>]) { 1067 break; 1068 } else { 1069 return Err(lookahead.error()); 1070 }); 1071 } 1072 let gt_token: Token![>] = input.parse()?; 1073 Ok(PreciseCapture { 1074 use_token, 1075 lt_token, 1076 params, 1077 gt_token, 1078 }) 1079 } 1080 } 1081 1082 #[cfg(feature = "full")] 1083 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 1084 impl Parse for CapturedParam { 1085 fn parse(input: ParseStream) -> Result<Self> { 1086 let lookahead = input.lookahead1(); 1087 if lookahead.peek(Lifetime) { 1088 input.parse().map(CapturedParam::Lifetime) 1089 } else if lookahead.peek(Ident) || input.peek(Token![Self]) { 1090 input.call(Ident::parse_any).map(CapturedParam::Ident) 1091 } else { 1092 Err(lookahead.error()) 1093 } 1094 } 1095 } 1096 1097 pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool { 1098 // Rust syntax has an ambiguity between generic parameters and qualified 1099 // paths. In `impl <T> :: Thing<T, U> {}` this may either be a generic 1100 // inherent impl `impl<T> ::Thing<T, U>` or a non-generic inherent impl 1101 // for an associated type `impl <T>::Thing<T, U>`. 1102 // 1103 // After `<` the following continuations can only begin generics, not a 1104 // qualified path: 1105 // 1106 // `<` `>` - empty generic parameters 1107 // `<` `#` - generic parameters with attribute 1108 // `<` LIFETIME `>` - single lifetime parameter 1109 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list 1110 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds 1111 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default 1112 // `<` const - generic const parameter 1113 // 1114 // The only truly ambiguous case is: 1115 // 1116 // `<` IDENT `>` `::` IDENT ... 1117 // 1118 // which we disambiguate in favor of generics because this is almost 1119 // always the expected one in the context of real-world code. 1120 input.peek(Token![<]) 1121 && (input.peek2(Token![>]) 1122 || input.peek2(Token![#]) 1123 || (input.peek2(Lifetime) || input.peek2(Ident)) 1124 && (input.peek3(Token![>]) 1125 || input.peek3(Token![,]) 1126 || input.peek3(Token![:]) && !input.peek3(Token![::]) 1127 || input.peek3(Token![=])) 1128 || input.peek2(Token![const])) 1129 } 1130 1131 #[cfg(feature = "full")] 1132 pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool { 1133 let input = input.fork(); 1134 input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where` 1135 choose_generics_over_qpath(&input) 1136 } 1137 } 1138 1139 #[cfg(feature = "printing")] 1140 pub(crate) mod printing { 1141 use crate::attr::FilterAttrs; 1142 #[cfg(feature = "full")] 1143 use crate::expr; 1144 use crate::expr::Expr; 1145 #[cfg(feature = "full")] 1146 use crate::fixup::FixupContext; 1147 use crate::generics::{ 1148 BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam, 1149 PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics, 1150 TypeParam, WhereClause, 1151 }; 1152 #[cfg(feature = "full")] 1153 use crate::generics::{CapturedParam, PreciseCapture}; 1154 use crate::print::TokensOrDefault; 1155 use crate::token; 1156 use proc_macro2::TokenStream; 1157 use quote::{ToTokens, TokenStreamExt}; 1158 1159 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1160 impl ToTokens for Generics { 1161 fn to_tokens(&self, tokens: &mut TokenStream) { 1162 if self.params.is_empty() { 1163 return; 1164 } 1165 1166 TokensOrDefault(&self.lt_token).to_tokens(tokens); 1167 1168 // Print lifetimes before types and consts, regardless of their 1169 // order in self.params. 1170 let mut trailing_or_empty = true; 1171 for param in self.params.pairs() { 1172 if let GenericParam::Lifetime(_) = **param.value() { 1173 param.to_tokens(tokens); 1174 trailing_or_empty = param.punct().is_some(); 1175 } 1176 } 1177 for param in self.params.pairs() { 1178 match param.value() { 1179 GenericParam::Type(_) | GenericParam::Const(_) => { 1180 if !trailing_or_empty { 1181 <Token![,]>::default().to_tokens(tokens); 1182 trailing_or_empty = true; 1183 } 1184 param.to_tokens(tokens); 1185 } 1186 GenericParam::Lifetime(_) => {} 1187 } 1188 } 1189 1190 TokensOrDefault(&self.gt_token).to_tokens(tokens); 1191 } 1192 } 1193 1194 impl<'a> ToTokens for ImplGenerics<'a> { 1195 fn to_tokens(&self, tokens: &mut TokenStream) { 1196 if self.0.params.is_empty() { 1197 return; 1198 } 1199 1200 TokensOrDefault(&self.0.lt_token).to_tokens(tokens); 1201 1202 // Print lifetimes before types and consts, regardless of their 1203 // order in self.params. 1204 let mut trailing_or_empty = true; 1205 for param in self.0.params.pairs() { 1206 if let GenericParam::Lifetime(_) = **param.value() { 1207 param.to_tokens(tokens); 1208 trailing_or_empty = param.punct().is_some(); 1209 } 1210 } 1211 for param in self.0.params.pairs() { 1212 if let GenericParam::Lifetime(_) = **param.value() { 1213 continue; 1214 } 1215 if !trailing_or_empty { 1216 <Token![,]>::default().to_tokens(tokens); 1217 trailing_or_empty = true; 1218 } 1219 match param.value() { 1220 GenericParam::Lifetime(_) => unreachable!(), 1221 GenericParam::Type(param) => { 1222 // Leave off the type parameter defaults 1223 tokens.append_all(param.attrs.outer()); 1224 param.ident.to_tokens(tokens); 1225 if !param.bounds.is_empty() { 1226 TokensOrDefault(¶m.colon_token).to_tokens(tokens); 1227 param.bounds.to_tokens(tokens); 1228 } 1229 } 1230 GenericParam::Const(param) => { 1231 // Leave off the const parameter defaults 1232 tokens.append_all(param.attrs.outer()); 1233 param.const_token.to_tokens(tokens); 1234 param.ident.to_tokens(tokens); 1235 param.colon_token.to_tokens(tokens); 1236 param.ty.to_tokens(tokens); 1237 } 1238 } 1239 param.punct().to_tokens(tokens); 1240 } 1241 1242 TokensOrDefault(&self.0.gt_token).to_tokens(tokens); 1243 } 1244 } 1245 1246 impl<'a> ToTokens for TypeGenerics<'a> { 1247 fn to_tokens(&self, tokens: &mut TokenStream) { 1248 if self.0.params.is_empty() { 1249 return; 1250 } 1251 1252 TokensOrDefault(&self.0.lt_token).to_tokens(tokens); 1253 1254 // Print lifetimes before types and consts, regardless of their 1255 // order in self.params. 1256 let mut trailing_or_empty = true; 1257 for param in self.0.params.pairs() { 1258 if let GenericParam::Lifetime(def) = *param.value() { 1259 // Leave off the lifetime bounds and attributes 1260 def.lifetime.to_tokens(tokens); 1261 param.punct().to_tokens(tokens); 1262 trailing_or_empty = param.punct().is_some(); 1263 } 1264 } 1265 for param in self.0.params.pairs() { 1266 if let GenericParam::Lifetime(_) = **param.value() { 1267 continue; 1268 } 1269 if !trailing_or_empty { 1270 <Token![,]>::default().to_tokens(tokens); 1271 trailing_or_empty = true; 1272 } 1273 match param.value() { 1274 GenericParam::Lifetime(_) => unreachable!(), 1275 GenericParam::Type(param) => { 1276 // Leave off the type parameter defaults 1277 param.ident.to_tokens(tokens); 1278 } 1279 GenericParam::Const(param) => { 1280 // Leave off the const parameter defaults 1281 param.ident.to_tokens(tokens); 1282 } 1283 } 1284 param.punct().to_tokens(tokens); 1285 } 1286 1287 TokensOrDefault(&self.0.gt_token).to_tokens(tokens); 1288 } 1289 } 1290 1291 impl<'a> ToTokens for Turbofish<'a> { 1292 fn to_tokens(&self, tokens: &mut TokenStream) { 1293 if !self.0.params.is_empty() { 1294 <Token![::]>::default().to_tokens(tokens); 1295 TypeGenerics(self.0).to_tokens(tokens); 1296 } 1297 } 1298 } 1299 1300 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1301 impl ToTokens for BoundLifetimes { 1302 fn to_tokens(&self, tokens: &mut TokenStream) { 1303 self.for_token.to_tokens(tokens); 1304 self.lt_token.to_tokens(tokens); 1305 self.lifetimes.to_tokens(tokens); 1306 self.gt_token.to_tokens(tokens); 1307 } 1308 } 1309 1310 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1311 impl ToTokens for LifetimeParam { 1312 fn to_tokens(&self, tokens: &mut TokenStream) { 1313 tokens.append_all(self.attrs.outer()); 1314 self.lifetime.to_tokens(tokens); 1315 if !self.bounds.is_empty() { 1316 TokensOrDefault(&self.colon_token).to_tokens(tokens); 1317 self.bounds.to_tokens(tokens); 1318 } 1319 } 1320 } 1321 1322 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1323 impl ToTokens for TypeParam { 1324 fn to_tokens(&self, tokens: &mut TokenStream) { 1325 tokens.append_all(self.attrs.outer()); 1326 self.ident.to_tokens(tokens); 1327 if !self.bounds.is_empty() { 1328 TokensOrDefault(&self.colon_token).to_tokens(tokens); 1329 self.bounds.to_tokens(tokens); 1330 } 1331 if let Some(default) = &self.default { 1332 TokensOrDefault(&self.eq_token).to_tokens(tokens); 1333 default.to_tokens(tokens); 1334 } 1335 } 1336 } 1337 1338 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1339 impl ToTokens for TraitBound { 1340 fn to_tokens(&self, tokens: &mut TokenStream) { 1341 let to_tokens = |tokens: &mut TokenStream| { 1342 self.modifier.to_tokens(tokens); 1343 self.lifetimes.to_tokens(tokens); 1344 self.path.to_tokens(tokens); 1345 }; 1346 match &self.paren_token { 1347 Some(paren) => paren.surround(tokens, to_tokens), 1348 None => to_tokens(tokens), 1349 } 1350 } 1351 } 1352 1353 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1354 impl ToTokens for TraitBoundModifier { 1355 fn to_tokens(&self, tokens: &mut TokenStream) { 1356 match self { 1357 TraitBoundModifier::None => {} 1358 TraitBoundModifier::Maybe(t) => t.to_tokens(tokens), 1359 } 1360 } 1361 } 1362 1363 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1364 impl ToTokens for ConstParam { 1365 fn to_tokens(&self, tokens: &mut TokenStream) { 1366 tokens.append_all(self.attrs.outer()); 1367 self.const_token.to_tokens(tokens); 1368 self.ident.to_tokens(tokens); 1369 self.colon_token.to_tokens(tokens); 1370 self.ty.to_tokens(tokens); 1371 if let Some(default) = &self.default { 1372 TokensOrDefault(&self.eq_token).to_tokens(tokens); 1373 print_const_argument(default, tokens); 1374 } 1375 } 1376 } 1377 1378 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1379 impl ToTokens for WhereClause { 1380 fn to_tokens(&self, tokens: &mut TokenStream) { 1381 if !self.predicates.is_empty() { 1382 self.where_token.to_tokens(tokens); 1383 self.predicates.to_tokens(tokens); 1384 } 1385 } 1386 } 1387 1388 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1389 impl ToTokens for PredicateLifetime { 1390 fn to_tokens(&self, tokens: &mut TokenStream) { 1391 self.lifetime.to_tokens(tokens); 1392 self.colon_token.to_tokens(tokens); 1393 self.bounds.to_tokens(tokens); 1394 } 1395 } 1396 1397 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1398 impl ToTokens for PredicateType { 1399 fn to_tokens(&self, tokens: &mut TokenStream) { 1400 self.lifetimes.to_tokens(tokens); 1401 self.bounded_ty.to_tokens(tokens); 1402 self.colon_token.to_tokens(tokens); 1403 self.bounds.to_tokens(tokens); 1404 } 1405 } 1406 1407 #[cfg(feature = "full")] 1408 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1409 impl ToTokens for PreciseCapture { 1410 fn to_tokens(&self, tokens: &mut TokenStream) { 1411 self.use_token.to_tokens(tokens); 1412 self.lt_token.to_tokens(tokens); 1413 1414 // Print lifetimes before types and consts, regardless of their 1415 // order in self.params. 1416 let mut trailing_or_empty = true; 1417 for param in self.params.pairs() { 1418 if let CapturedParam::Lifetime(_) = **param.value() { 1419 param.to_tokens(tokens); 1420 trailing_or_empty = param.punct().is_some(); 1421 } 1422 } 1423 for param in self.params.pairs() { 1424 if let CapturedParam::Ident(_) = **param.value() { 1425 if !trailing_or_empty { 1426 <Token![,]>::default().to_tokens(tokens); 1427 trailing_or_empty = true; 1428 } 1429 param.to_tokens(tokens); 1430 } 1431 } 1432 1433 self.gt_token.to_tokens(tokens); 1434 } 1435 } 1436 1437 #[cfg(feature = "full")] 1438 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 1439 impl ToTokens for CapturedParam { 1440 fn to_tokens(&self, tokens: &mut TokenStream) { 1441 match self { 1442 CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens), 1443 CapturedParam::Ident(ident) => ident.to_tokens(tokens), 1444 } 1445 } 1446 } 1447 1448 pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) { 1449 match expr { 1450 Expr::Lit(expr) => expr.to_tokens(tokens), 1451 1452 Expr::Path(expr) 1453 if expr.attrs.is_empty() 1454 && expr.qself.is_none() 1455 && expr.path.get_ident().is_some() => 1456 { 1457 expr.to_tokens(tokens); 1458 } 1459 1460 #[cfg(feature = "full")] 1461 Expr::Block(expr) => expr.to_tokens(tokens), 1462 1463 #[cfg(not(feature = "full"))] 1464 Expr::Verbatim(expr) => expr.to_tokens(tokens), 1465 1466 // ERROR CORRECTION: Add braces to make sure that the 1467 // generated code is valid. 1468 _ => token::Brace::default().surround(tokens, |tokens| { 1469 #[cfg(feature = "full")] 1470 expr::printing::print_expr(expr, tokens, FixupContext::new_stmt()); 1471 1472 #[cfg(not(feature = "full"))] 1473 expr.to_tokens(tokens); 1474 }), 1475 } 1476 } 1477 } 1478