File Index
Files and directories
Sign in
FILE

generics.rs

File preview with syntax highlighting.

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