syn/
generics.rs

1use crate::attr::Attribute;
2use crate::expr::Expr;
3use crate::ident::Ident;
4use crate::lifetime::Lifetime;
5use crate::path::Path;
6use crate::punctuated::{Iter, IterMut, Punctuated};
7use crate::token;
8use crate::ty::Type;
9use alloc::vec::Vec;
10#[cfg(all(feature = "printing", feature = "extra-traits"))]
11use core::fmt::{self, Debug};
12#[cfg(all(feature = "printing", feature = "extra-traits"))]
13use core::hash::{Hash, Hasher};
14use proc_macro2::TokenStream;
15
16#[doc =
r" Lifetimes and type parameters attached to a declaration of a function,"]
#[doc = r" enum, trait, etc."]
#[doc = r""]
#[doc = r" This struct represents two distinct optional syntactic elements,"]
#[doc = r" [generic parameters] and [where clause]. In some locations of the"]
#[doc = r" grammar, there may be other tokens in between these two things."]
#[doc = r""]
#[doc =
r" [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters"]
#[doc =
r" [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses"]
pub struct Generics {
    pub lt_token: Option<crate::token::Lt>,
    pub params: Punctuated<GenericParam, crate::token::Comma>,
    pub gt_token: Option<crate::token::Gt>,
    pub where_clause: Option<WhereClause>,
}ast_struct! {
17    /// Lifetimes and type parameters attached to a declaration of a function,
18    /// enum, trait, etc.
19    ///
20    /// This struct represents two distinct optional syntactic elements,
21    /// [generic parameters] and [where clause]. In some locations of the
22    /// grammar, there may be other tokens in between these two things.
23    ///
24    /// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters
25    /// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses
26    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
27    pub struct Generics {
28        pub lt_token: Option<Token![<]>,
29        pub params: Punctuated<GenericParam, Token![,]>,
30        pub gt_token: Option<Token![>]>,
31        pub where_clause: Option<WhereClause>,
32    }
33}
34
35#[doc =
r" A generic type parameter, lifetime, or const generic: `T: Into<String>`,"]
#[doc = r" `'a: 'b`, `const LEN: usize`."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
pub enum GenericParam {

    #[doc = r" A lifetime parameter: `'a: 'b + 'c + 'd`."]
    Lifetime(LifetimeParam),

    #[doc = r" A generic type parameter: `T: Into<String>`."]
    Type(TypeParam),

    #[doc = r" A const generic parameter: `const LENGTH: usize`."]
    Const(ConstParam),
}
impl From<LifetimeParam> for GenericParam {
    fn from(e: LifetimeParam) -> GenericParam { GenericParam::Lifetime(e) }
}
impl From<TypeParam> for GenericParam {
    fn from(e: TypeParam) -> GenericParam { GenericParam::Type(e) }
}
impl From<ConstParam> for GenericParam {
    fn from(e: ConstParam) -> GenericParam { GenericParam::Const(e) }
}
impl ::quote::ToTokens for GenericParam {
    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
        match self {
            GenericParam::Lifetime(_e) => _e.to_tokens(tokens),
            GenericParam::Type(_e) => _e.to_tokens(tokens),
            GenericParam::Const(_e) => _e.to_tokens(tokens),
        }
    }
}ast_enum_of_structs! {
36    /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
37    /// `'a: 'b`, `const LEN: usize`.
38    ///
39    /// # Syntax tree enum
40    ///
41    /// This type is a [syntax tree enum].
42    ///
43    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
44    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
45    pub enum GenericParam {
46        /// A lifetime parameter: `'a: 'b + 'c + 'd`.
47        Lifetime(LifetimeParam),
48
49        /// A generic type parameter: `T: Into<String>`.
50        Type(TypeParam),
51
52        /// A const generic parameter: `const LENGTH: usize`.
53        Const(ConstParam),
54    }
55}
56
57#[doc = r" A lifetime definition: `'a: 'b + 'c + 'd`."]
pub struct LifetimeParam {
    pub attrs: Vec<Attribute>,
    pub lifetime: Lifetime,
    pub colon_token: Option<crate::token::Colon>,
    pub bounds: Punctuated<Lifetime, crate::token::Plus>,
}ast_struct! {
58    /// A lifetime definition: `'a: 'b + 'c + 'd`.
59    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
60    pub struct LifetimeParam {
61        pub attrs: Vec<Attribute>,
62        pub lifetime: Lifetime,
63        pub colon_token: Option<Token![:]>,
64        pub bounds: Punctuated<Lifetime, Token![+]>,
65    }
66}
67
68#[doc = r" A generic type parameter: `T: Into<String>`."]
pub struct TypeParam {
    pub attrs: Vec<Attribute>,
    pub ident: Ident,
    pub colon_token: Option<crate::token::Colon>,
    pub bounds: Punctuated<TypeParamBound, crate::token::Plus>,
    pub eq_token: Option<crate::token::Eq>,
    pub default: Option<Type>,
}ast_struct! {
69    /// A generic type parameter: `T: Into<String>`.
70    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
71    pub struct TypeParam {
72        pub attrs: Vec<Attribute>,
73        pub ident: Ident,
74        pub colon_token: Option<Token![:]>,
75        pub bounds: Punctuated<TypeParamBound, Token![+]>,
76        pub eq_token: Option<Token![=]>,
77        pub default: Option<Type>,
78    }
79}
80
81#[doc = r" A const generic parameter: `const LENGTH: usize`."]
pub struct ConstParam {
    pub attrs: Vec<Attribute>,
    pub const_token: crate::token::Const,
    pub ident: Ident,
    pub colon_token: crate::token::Colon,
    pub ty: Type,
    pub eq_token: Option<crate::token::Eq>,
    pub default: Option<Expr>,
}ast_struct! {
82    /// A const generic parameter: `const LENGTH: usize`.
83    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
84    pub struct ConstParam {
85        pub attrs: Vec<Attribute>,
86        pub const_token: Token![const],
87        pub ident: Ident,
88        pub colon_token: Token![:],
89        pub ty: Type,
90        pub eq_token: Option<Token![=]>,
91        pub default: Option<Expr>,
92    }
93}
94
95impl Default for Generics {
96    fn default() -> Self {
97        Generics {
98            lt_token: None,
99            params: Punctuated::new(),
100            gt_token: None,
101            where_clause: None,
102        }
103    }
104}
105
106impl Generics {
107    return_impl_trait! {
108        /// Iterator over the lifetime parameters in `self.params`.
109        pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] {
110            Lifetimes(self.params.iter())
111        }
112    }
113
114    return_impl_trait! {
115        /// Iterator over the lifetime parameters in `self.params`.
116        pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> [LifetimesMut] {
117            LifetimesMut(self.params.iter_mut())
118        }
119    }
120
121    return_impl_trait! {
122        /// Iterator over the type parameters in `self.params`.
123        pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] {
124            TypeParams(self.params.iter())
125        }
126    }
127
128    return_impl_trait! {
129        /// Iterator over the type parameters in `self.params`.
130        pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> [TypeParamsMut] {
131            TypeParamsMut(self.params.iter_mut())
132        }
133    }
134
135    return_impl_trait! {
136        /// Iterator over the constant parameters in `self.params`.
137        pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] {
138            ConstParams(self.params.iter())
139        }
140    }
141
142    return_impl_trait! {
143        /// Iterator over the constant parameters in `self.params`.
144        pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] {
145            ConstParamsMut(self.params.iter_mut())
146        }
147    }
148
149    /// Initializes an empty `where`-clause if there is not one present already.
150    pub fn make_where_clause(&mut self) -> &mut WhereClause {
151        self.where_clause.get_or_insert_with(|| WhereClause {
152            where_token: <crate::token::WhereToken![where]>::default(),
153            predicates: Punctuated::new(),
154        })
155    }
156
157    /// Split a type's generics into the pieces required for impl'ing a trait
158    /// for that type.
159    ///
160    /// ```
161    /// # use proc_macro2::{Span, Ident};
162    /// # use quote::quote;
163    /// #
164    /// # let generics: syn::Generics = Default::default();
165    /// # let name = Ident::new("MyType", Span::call_site());
166    /// #
167    /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
168    /// quote! {
169    ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
170    ///         // ...
171    ///     }
172    /// }
173    /// # ;
174    /// ```
175    #[cfg(feature = "printing")]
176    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
177    pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
178        (
179            ImplGenerics(self),
180            TypeGenerics(self),
181            self.where_clause.as_ref(),
182        )
183    }
184}
185
186pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
187
188impl<'a> Iterator for Lifetimes<'a> {
189    type Item = &'a LifetimeParam;
190
191    fn next(&mut self) -> Option<Self::Item> {
192        if let GenericParam::Lifetime(lifetime) = self.0.next()? {
193            Some(lifetime)
194        } else {
195            self.next()
196        }
197    }
198}
199
200pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
201
202impl<'a> Iterator for LifetimesMut<'a> {
203    type Item = &'a mut LifetimeParam;
204
205    fn next(&mut self) -> Option<Self::Item> {
206        if let GenericParam::Lifetime(lifetime) = self.0.next()? {
207            Some(lifetime)
208        } else {
209            self.next()
210        }
211    }
212}
213
214pub struct TypeParams<'a>(Iter<'a, GenericParam>);
215
216impl<'a> Iterator for TypeParams<'a> {
217    type Item = &'a TypeParam;
218
219    fn next(&mut self) -> Option<Self::Item> {
220        if let GenericParam::Type(type_param) = self.0.next()? {
221            Some(type_param)
222        } else {
223            self.next()
224        }
225    }
226}
227
228pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
229
230impl<'a> Iterator for TypeParamsMut<'a> {
231    type Item = &'a mut TypeParam;
232
233    fn next(&mut self) -> Option<Self::Item> {
234        if let GenericParam::Type(type_param) = self.0.next()? {
235            Some(type_param)
236        } else {
237            self.next()
238        }
239    }
240}
241
242pub struct ConstParams<'a>(Iter<'a, GenericParam>);
243
244impl<'a> Iterator for ConstParams<'a> {
245    type Item = &'a ConstParam;
246
247    fn next(&mut self) -> Option<Self::Item> {
248        if let GenericParam::Const(const_param) = self.0.next()? {
249            Some(const_param)
250        } else {
251            self.next()
252        }
253    }
254}
255
256pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
257
258impl<'a> Iterator for ConstParamsMut<'a> {
259    type Item = &'a mut ConstParam;
260
261    fn next(&mut self) -> Option<Self::Item> {
262        if let GenericParam::Const(const_param) = self.0.next()? {
263            Some(const_param)
264        } else {
265            self.next()
266        }
267    }
268}
269
270/// Returned by `Generics::split_for_impl`.
271#[cfg(feature = "printing")]
272#[cfg_attr(
273    docsrs,
274    doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
275)]
276pub struct ImplGenerics<'a>(&'a Generics);
277
278/// Returned by `Generics::split_for_impl`.
279#[cfg(feature = "printing")]
280#[cfg_attr(
281    docsrs,
282    doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
283)]
284pub struct TypeGenerics<'a>(&'a Generics);
285
286/// Returned by `TypeGenerics::as_turbofish`.
287#[cfg(feature = "printing")]
288#[cfg_attr(
289    docsrs,
290    doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
291)]
292pub struct Turbofish<'a>(&'a Generics);
293
294#[cfg(feature = "printing")]
295macro_rules! generics_wrapper_impls {
296    ($ty:ident) => {
297        #[cfg(feature = "clone-impls")]
298        #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
299        impl<'a> Clone for $ty<'a> {
300            fn clone(&self) -> Self {
301                $ty(self.0)
302            }
303        }
304
305        #[cfg(feature = "extra-traits")]
306        #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
307        impl<'a> Debug for $ty<'a> {
308            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
309                formatter
310                    .debug_tuple(stringify!($ty))
311                    .field(self.0)
312                    .finish()
313            }
314        }
315
316        #[cfg(feature = "extra-traits")]
317        #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
318        impl<'a> Eq for $ty<'a> {}
319
320        #[cfg(feature = "extra-traits")]
321        #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
322        impl<'a> PartialEq for $ty<'a> {
323            fn eq(&self, other: &Self) -> bool {
324                self.0 == other.0
325            }
326        }
327
328        #[cfg(feature = "extra-traits")]
329        #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
330        impl<'a> Hash for $ty<'a> {
331            fn hash<H: Hasher>(&self, state: &mut H) {
332                self.0.hash(state);
333            }
334        }
335    };
336}
337
338#[cfg(feature = "printing")]
339impl<'a> Clone for ImplGenerics<'a> {
    fn clone(&self) -> Self { ImplGenerics(self.0) }
}
impl<'a> Debug for ImplGenerics<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("ImplGenerics").field(self.0).finish()
    }
}
impl<'a> Eq for ImplGenerics<'a> { }
impl<'a> PartialEq for ImplGenerics<'a> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'a> Hash for ImplGenerics<'a> {
    fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}generics_wrapper_impls!(ImplGenerics);
340#[cfg(feature = "printing")]
341impl<'a> Clone for TypeGenerics<'a> {
    fn clone(&self) -> Self { TypeGenerics(self.0) }
}
impl<'a> Debug for TypeGenerics<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("TypeGenerics").field(self.0).finish()
    }
}
impl<'a> Eq for TypeGenerics<'a> { }
impl<'a> PartialEq for TypeGenerics<'a> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'a> Hash for TypeGenerics<'a> {
    fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}generics_wrapper_impls!(TypeGenerics);
342#[cfg(feature = "printing")]
343impl<'a> Clone for Turbofish<'a> {
    fn clone(&self) -> Self { Turbofish(self.0) }
}
impl<'a> Debug for Turbofish<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("Turbofish").field(self.0).finish()
    }
}
impl<'a> Eq for Turbofish<'a> { }
impl<'a> PartialEq for Turbofish<'a> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
impl<'a> Hash for Turbofish<'a> {
    fn hash<H: Hasher>(&self, state: &mut H) { self.0.hash(state); }
}generics_wrapper_impls!(Turbofish);
344
345#[cfg(feature = "printing")]
346impl<'a> TypeGenerics<'a> {
347    /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
348    pub fn as_turbofish(&self) -> Turbofish<'a> {
349        Turbofish(self.0)
350    }
351}
352
353#[doc = r" A set of bound lifetimes: `for<'a, 'b, 'c>`."]
pub struct BoundLifetimes {
    pub for_token: crate::token::For,
    pub lt_token: crate::token::Lt,
    pub lifetimes: Punctuated<GenericParam, crate::token::Comma>,
    pub gt_token: crate::token::Gt,
}ast_struct! {
354    /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
355    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
356    pub struct BoundLifetimes {
357        pub for_token: Token![for],
358        pub lt_token: Token![<],
359        pub lifetimes: Punctuated<GenericParam, Token![,]>,
360        pub gt_token: Token![>],
361    }
362}
363
364impl Default for BoundLifetimes {
365    fn default() -> Self {
366        BoundLifetimes {
367            for_token: Default::default(),
368            lt_token: Default::default(),
369            lifetimes: Punctuated::new(),
370            gt_token: Default::default(),
371        }
372    }
373}
374
375impl LifetimeParam {
376    pub fn new(lifetime: Lifetime) -> Self {
377        LifetimeParam {
378            attrs: Vec::new(),
379            lifetime,
380            colon_token: None,
381            bounds: Punctuated::new(),
382        }
383    }
384}
385
386impl From<Ident> for TypeParam {
387    fn from(ident: Ident) -> Self {
388        TypeParam {
389            attrs: Vec::new(),
390            ident,
391            colon_token: None,
392            bounds: Punctuated::new(),
393            eq_token: None,
394            default: None,
395        }
396    }
397}
398
399#[doc = r" A trait or lifetime used as a bound on a type parameter."]
#[non_exhaustive]
pub enum TypeParamBound {
    Trait(TraitBound),
    Lifetime(Lifetime),
    PreciseCapture(PreciseCapture),
    Verbatim(TokenStream),
}
impl From<TraitBound> for TypeParamBound {
    fn from(e: TraitBound) -> TypeParamBound { TypeParamBound::Trait(e) }
}
impl From<Lifetime> for TypeParamBound {
    fn from(e: Lifetime) -> TypeParamBound { TypeParamBound::Lifetime(e) }
}
impl From<PreciseCapture> for TypeParamBound {
    fn from(e: PreciseCapture) -> TypeParamBound {
        TypeParamBound::PreciseCapture(e)
    }
}
impl ::quote::ToTokens for TypeParamBound {
    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
        match self {
            TypeParamBound::Trait(_e) => _e.to_tokens(tokens),
            TypeParamBound::Lifetime(_e) => _e.to_tokens(tokens),
            TypeParamBound::PreciseCapture(_e) => _e.to_tokens(tokens),
            TypeParamBound::Verbatim(_e) => _e.to_tokens(tokens),
        }
    }
}ast_enum_of_structs! {
400    /// A trait or lifetime used as a bound on a type parameter.
401    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
402    #[non_exhaustive]
403    pub enum TypeParamBound {
404        Trait(TraitBound),
405        Lifetime(Lifetime),
406        PreciseCapture(PreciseCapture),
407        Verbatim(TokenStream),
408    }
409}
410
411#[doc = r" A trait used as a bound on a type parameter."]
pub struct TraitBound {
    pub paren_token: Option<token::Paren>,
    pub modifier: TraitBoundModifier,
    #[doc = r" The `for<'a>` in `for<'a> Foo<&'a T>`"]
    pub lifetimes: Option<BoundLifetimes>,
    #[doc = r" The `Foo<&'a T>` in `for<'a> Foo<&'a T>`"]
    pub path: Path,
}ast_struct! {
412    /// A trait used as a bound on a type parameter.
413    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
414    pub struct TraitBound {
415        pub paren_token: Option<token::Paren>,
416        pub modifier: TraitBoundModifier,
417        /// The `for<'a>` in `for<'a> Foo<&'a T>`
418        pub lifetimes: Option<BoundLifetimes>,
419        /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
420        pub path: Path,
421    }
422}
423
424#[doc = r" A modifier on a trait bound, currently only used for the `?` in"]
#[doc = r" `?Sized`."]
pub enum TraitBoundModifier { None, Maybe(crate::token::Question), }ast_enum! {
425    /// A modifier on a trait bound, currently only used for the `?` in
426    /// `?Sized`.
427    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
428    pub enum TraitBoundModifier {
429        None,
430        Maybe(Token![?]),
431    }
432}
433
434#[doc =
r" Precise capturing bound: the 'use&lt;&hellip;&gt;' in `impl Trait +"]
#[doc = r" use<'a, T>`."]
pub struct PreciseCapture {
    pub use_token: crate::token::Use,
    pub lt_token: crate::token::Lt,
    pub params: Punctuated<CapturedParam, crate::token::Comma>,
    pub gt_token: crate::token::Gt,
}ast_struct! {
435    /// Precise capturing bound: the 'use&lt;&hellip;&gt;' in `impl Trait +
436    /// use<'a, T>`.
437    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
438    pub struct PreciseCapture #full {
439        pub use_token: Token![use],
440        pub lt_token: Token![<],
441        pub params: Punctuated<CapturedParam, Token![,]>,
442        pub gt_token: Token![>],
443    }
444}
445
446#[cfg(feature = "full")]
447#[doc = r" Single parameter in a precise capturing bound."]
#[non_exhaustive]
pub enum CapturedParam {

    #[doc =
    r" A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl"]
    #[doc = r" Trait + use<'a>`."]
    Lifetime(Lifetime),

    #[doc =
    r" A type parameter or const generic parameter in precise capturing"]
    #[doc =
    r" bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() ->"]
    #[doc = r" impl Trait + use<K>`."]
    Ident(Ident),
}ast_enum! {
448    /// Single parameter in a precise capturing bound.
449    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
450    #[non_exhaustive]
451    pub enum CapturedParam {
452        /// A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl
453        /// Trait + use<'a>`.
454        Lifetime(Lifetime),
455        /// A type parameter or const generic parameter in precise capturing
456        /// bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() ->
457        /// impl Trait + use<K>`.
458        Ident(Ident),
459    }
460}
461
462#[doc = r" A `where` clause in a definition: `where T: Deserialize<'de>, D:"]
#[doc = r" 'static`."]
pub struct WhereClause {
    pub where_token: crate::token::Where,
    pub predicates: Punctuated<WherePredicate, crate::token::Comma>,
}ast_struct! {
463    /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
464    /// 'static`.
465    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
466    pub struct WhereClause {
467        pub where_token: Token![where],
468        pub predicates: Punctuated<WherePredicate, Token![,]>,
469    }
470}
471
472#[doc = r" A single predicate in a `where` clause: `T: Deserialize<'de>`."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
#[non_exhaustive]
pub enum WherePredicate {

    #[doc = r" A lifetime predicate in a `where` clause: `'a: 'b + 'c`."]
    Lifetime(PredicateLifetime),

    #[doc =
    r" A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`."]
    Type(PredicateType),
}
impl From<PredicateLifetime> for WherePredicate {
    fn from(e: PredicateLifetime) -> WherePredicate {
        WherePredicate::Lifetime(e)
    }
}
impl From<PredicateType> for WherePredicate {
    fn from(e: PredicateType) -> WherePredicate { WherePredicate::Type(e) }
}
impl ::quote::ToTokens for WherePredicate {
    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
        match self {
            WherePredicate::Lifetime(_e) => _e.to_tokens(tokens),
            WherePredicate::Type(_e) => _e.to_tokens(tokens),
        }
    }
}ast_enum_of_structs! {
473    /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
474    ///
475    /// # Syntax tree enum
476    ///
477    /// This type is a [syntax tree enum].
478    ///
479    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
480    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
481    #[non_exhaustive]
482    pub enum WherePredicate {
483        /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
484        Lifetime(PredicateLifetime),
485
486        /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
487        Type(PredicateType),
488    }
489}
490
491#[doc = r" A lifetime predicate in a `where` clause: `'a: 'b + 'c`."]
pub struct PredicateLifetime {
    pub lifetime: Lifetime,
    pub colon_token: crate::token::Colon,
    pub bounds: Punctuated<Lifetime, crate::token::Plus>,
}ast_struct! {
492    /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
493    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
494    pub struct PredicateLifetime {
495        pub lifetime: Lifetime,
496        pub colon_token: Token![:],
497        pub bounds: Punctuated<Lifetime, Token![+]>,
498    }
499}
500
501#[doc =
r" A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`."]
pub struct PredicateType {
    #[doc = r" Any lifetimes from a `for` binding"]
    pub lifetimes: Option<BoundLifetimes>,
    #[doc = r" The type being bounded"]
    pub bounded_ty: Type,
    pub colon_token: crate::token::Colon,
    #[doc = r" Trait and lifetime bounds (`Clone+Send+'static`)"]
    pub bounds: Punctuated<TypeParamBound, crate::token::Plus>,
}ast_struct! {
502    /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
503    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
504    pub struct PredicateType {
505        /// Any lifetimes from a `for` binding
506        pub lifetimes: Option<BoundLifetimes>,
507        /// The type being bounded
508        pub bounded_ty: Type,
509        pub colon_token: Token![:],
510        /// Trait and lifetime bounds (`Clone+Send+'static`)
511        pub bounds: Punctuated<TypeParamBound, Token![+]>,
512    }
513}
514
515#[cfg(feature = "parsing")]
516pub(crate) mod parsing {
517    use crate::attr::Attribute;
518    #[cfg(feature = "full")]
519    use crate::error;
520    use crate::error::{Error, Result};
521    use crate::ext::IdentExt as _;
522    use crate::generics::{
523        BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
524        PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
525        WherePredicate,
526    };
527    #[cfg(feature = "full")]
528    use crate::generics::{CapturedParam, PreciseCapture};
529    use crate::ident::Ident;
530    use crate::lifetime::Lifetime;
531    use crate::parse::{Parse, ParseStream};
532    use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments};
533    use crate::punctuated::Punctuated;
534    use crate::token;
535    use crate::ty::Type;
536    use crate::verbatim;
537
538    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
539    impl Parse for Generics {
540        fn parse(input: ParseStream) -> Result<Self> {
541            if !input.peek(crate::token::LtToken![<]) {
542                return Ok(Generics::default());
543            }
544
545            let lt_token: crate::token::LtToken![<] = input.parse()?;
546
547            let mut params = Punctuated::new();
548            loop {
549                if input.peek(crate::token::GtToken![>]) {
550                    break;
551                }
552
553                let attrs = input.call(Attribute::parse_outer)?;
554                let lookahead = input.lookahead1();
555                if lookahead.peek(Lifetime) {
556                    params.push_value(GenericParam::Lifetime(LifetimeParam {
557                        attrs,
558                        ..input.parse()?
559                    }));
560                } else if lookahead.peek(Ident) {
561                    params.push_value(GenericParam::Type(TypeParam {
562                        attrs,
563                        ..input.parse()?
564                    }));
565                } else if lookahead.peek(crate::token::ConstToken![const]) {
566                    params.push_value(GenericParam::Const(ConstParam {
567                        attrs,
568                        ..input.parse()?
569                    }));
570                } else if input.peek(crate::token::UnderscoreToken![_]) {
571                    params.push_value(GenericParam::Type(TypeParam {
572                        attrs,
573                        ident: input.call(Ident::parse_any)?,
574                        colon_token: None,
575                        bounds: Punctuated::new(),
576                        eq_token: None,
577                        default: None,
578                    }));
579                } else {
580                    return Err(lookahead.error());
581                }
582
583                if input.peek(crate::token::GtToken![>]) {
584                    break;
585                }
586                let punct = input.parse()?;
587                params.push_punct(punct);
588            }
589
590            let gt_token: crate::token::GtToken![>] = input.parse()?;
591
592            Ok(Generics {
593                lt_token: Some(lt_token),
594                params,
595                gt_token: Some(gt_token),
596                where_clause: None,
597            })
598        }
599    }
600
601    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
602    impl Parse for GenericParam {
603        fn parse(input: ParseStream) -> Result<Self> {
604            let attrs = input.call(Attribute::parse_outer)?;
605
606            let lookahead = input.lookahead1();
607            if lookahead.peek(Ident) {
608                Ok(GenericParam::Type(TypeParam {
609                    attrs,
610                    ..input.parse()?
611                }))
612            } else if lookahead.peek(Lifetime) {
613                Ok(GenericParam::Lifetime(LifetimeParam {
614                    attrs,
615                    ..input.parse()?
616                }))
617            } else if lookahead.peek(crate::token::ConstToken![const]) {
618                Ok(GenericParam::Const(ConstParam {
619                    attrs,
620                    ..input.parse()?
621                }))
622            } else {
623                Err(lookahead.error())
624            }
625        }
626    }
627
628    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
629    impl Parse for LifetimeParam {
630        fn parse(input: ParseStream) -> Result<Self> {
631            let has_colon;
632            Ok(LifetimeParam {
633                attrs: input.call(Attribute::parse_outer)?,
634                lifetime: input.parse()?,
635                colon_token: {
636                    if input.peek(crate::token::ColonToken![:]) {
637                        has_colon = true;
638                        Some(input.parse()?)
639                    } else {
640                        has_colon = false;
641                        None
642                    }
643                },
644                bounds: {
645                    let mut bounds = Punctuated::new();
646                    if has_colon {
647                        loop {
648                            if input.is_empty() || input.peek(crate::token::CommaToken![,]) || input.peek(crate::token::GtToken![>]) {
649                                break;
650                            }
651                            let value = input.parse()?;
652                            bounds.push_value(value);
653                            if !input.peek(crate::token::PlusToken![+]) {
654                                break;
655                            }
656                            let punct = input.parse()?;
657                            bounds.push_punct(punct);
658                        }
659                    }
660                    bounds
661                },
662            })
663        }
664    }
665
666    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
667    impl Parse for BoundLifetimes {
668        fn parse(input: ParseStream) -> Result<Self> {
669            Ok(BoundLifetimes {
670                for_token: input.parse()?,
671                lt_token: input.parse()?,
672                lifetimes: {
673                    let mut lifetimes = Punctuated::new();
674                    while !input.peek(crate::token::GtToken![>]) {
675                        lifetimes.push_value(input.parse()?);
676                        if input.peek(crate::token::GtToken![>]) {
677                            break;
678                        }
679                        lifetimes.push_punct(input.parse()?);
680                    }
681                    lifetimes
682                },
683                gt_token: input.parse()?,
684            })
685        }
686    }
687
688    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
689    impl Parse for Option<BoundLifetimes> {
690        fn parse(input: ParseStream) -> Result<Self> {
691            if input.peek(crate::token::ForToken![for]) {
692                input.parse().map(Some)
693            } else {
694                Ok(None)
695            }
696        }
697    }
698
699    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
700    impl Parse for TypeParam {
701        fn parse(input: ParseStream) -> Result<Self> {
702            let attrs = input.call(Attribute::parse_outer)?;
703            let ident: Ident = input.parse()?;
704            let colon_token: Option<crate::token::ColonToken![:]> = input.parse()?;
705
706            let mut bounds = Punctuated::new();
707            if colon_token.is_some() {
708                loop {
709                    if input.is_empty()
710                        || input.peek(crate::token::CommaToken![,])
711                        || input.peek(crate::token::GtToken![>])
712                        || input.peek(crate::token::EqToken![=])
713                    {
714                        break;
715                    }
716                    bounds.push_value({
717                        let allow_precise_capture = false;
718                        let allow_const = true;
719                        TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
720                    });
721                    if !input.peek(crate::token::PlusToken![+]) {
722                        break;
723                    }
724                    let punct: crate::token::PlusToken![+] = input.parse()?;
725                    bounds.push_punct(punct);
726                }
727            }
728
729            let eq_token: Option<crate::token::EqToken![=]> = input.parse()?;
730            let default = if eq_token.is_some() {
731                Some(input.parse::<Type>()?)
732            } else {
733                None
734            };
735
736            Ok(TypeParam {
737                attrs,
738                ident,
739                colon_token,
740                bounds,
741                eq_token,
742                default,
743            })
744        }
745    }
746
747    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
748    impl Parse for TypeParamBound {
749        fn parse(input: ParseStream) -> Result<Self> {
750            let allow_precise_capture = true;
751            let allow_const = true;
752            Self::parse_single(input, allow_precise_capture, allow_const)
753        }
754    }
755
756    impl TypeParamBound {
757        pub(crate) fn parse_single(
758            input: ParseStream,
759            #[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool,
760            allow_const: bool,
761        ) -> Result<Self> {
762            if input.peek(Lifetime) {
763                return input.parse().map(TypeParamBound::Lifetime);
764            }
765
766            #[cfg(feature = "full")]
767            {
768                if input.peek(crate::token::UseToken![use]) {
769                    let precise_capture: PreciseCapture = input.parse()?;
770                    return if allow_precise_capture {
771                        Ok(TypeParamBound::PreciseCapture(precise_capture))
772                    } else {
773                        let msg = "`use<...>` precise capturing syntax is not allowed here";
774                        Err(error::new2(
775                            precise_capture.use_token.span,
776                            precise_capture.gt_token.span,
777                            msg,
778                        ))
779                    };
780                }
781            }
782
783            let begin = input.fork();
784
785            let content;
786            let (paren_token, content) = if input.peek(token::Paren) {
787                (Some(match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input)), &content)
788            } else {
789                (None, input)
790            };
791
792            if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? {
793                bound.paren_token = paren_token;
794                Ok(TypeParamBound::Trait(bound))
795            } else {
796                Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input)))
797            }
798        }
799
800        pub(crate) fn parse_multiple(
801            input: ParseStream,
802            allow_plus: bool,
803            allow_precise_capture: bool,
804            allow_const: bool,
805        ) -> Result<Punctuated<Self, crate::token::PlusToken![+]>> {
806            let mut bounds = Punctuated::new();
807            loop {
808                let bound = Self::parse_single(input, allow_precise_capture, allow_const)?;
809                bounds.push_value(bound);
810                if !(allow_plus && input.peek(crate::token::PlusToken![+])) {
811                    break;
812                }
813                bounds.push_punct(input.parse()?);
814                if !(input.peek(Ident::peek_any)
815                    || input.peek(crate::token::PathSepToken![::])
816                    || input.peek(crate::token::QuestionToken![?])
817                    || input.peek(Lifetime)
818                    || input.peek(token::Paren)
819                    || (allow_const && (input.peek(token::Bracket) || input.peek(crate::token::ConstToken![const]))))
820                {
821                    break;
822                }
823            }
824            Ok(bounds)
825        }
826    }
827
828    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
829    impl Parse for TraitBound {
830        fn parse(input: ParseStream) -> Result<Self> {
831            let allow_const = false;
832            Self::do_parse(input, allow_const).map(Option::unwrap)
833        }
834    }
835
836    impl TraitBound {
837        fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> {
838            let mut lifetimes: Option<BoundLifetimes> = input.parse()?;
839
840            let is_conditionally_const = truecfg!(feature = "full") && input.peek(token::Bracket);
841            let is_unconditionally_const = truecfg!(feature = "full") && input.peek(crate::token::ConstToken![const]);
842            if is_conditionally_const {
843                let conditionally_const;
844                let bracket_token = match crate::__private::parse_brackets(&input) {
    crate::__private::Ok(brackets) => {
        conditionally_const = brackets.content;
        _ = conditionally_const;
        brackets.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(conditionally_const in input);
845                conditionally_const.parse::<crate::token::ConstToken![const]>()?;
846                if !allow_const {
847                    let msg = "`[const]` is not allowed here";
848                    return Err(Error::new(bracket_token.span.join(), msg));
849                }
850            } else if is_unconditionally_const {
851                let const_token: crate::token::ConstToken![const] = input.parse()?;
852                if !allow_const {
853                    let msg = "`const` is not allowed here";
854                    return Err(Error::new(const_token.span, msg));
855                }
856            }
857
858            let modifier: TraitBoundModifier = input.parse()?;
859            if lifetimes.is_none() && #[allow(non_exhaustive_omitted_patterns)] match modifier {
    TraitBoundModifier::Maybe(_) => true,
    _ => false,
}matches!(modifier, TraitBoundModifier::Maybe(_)) {
860                lifetimes = input.parse()?;
861            }
862
863            let mut path: Path = input.parse()?;
864            if path.segments.last().unwrap().arguments.is_empty()
865                && (input.peek(token::Paren) || input.peek(crate::token::PathSepToken![::]) && input.peek3(token::Paren))
866            {
867                input.parse::<Option<crate::token::PathSepToken![::]>>()?;
868                let args: ParenthesizedGenericArguments = input.parse()?;
869                let parenthesized = PathArguments::Parenthesized(args);
870                path.segments.last_mut().unwrap().arguments = parenthesized;
871            }
872
873            if lifetimes.is_some() {
874                match modifier {
875                    TraitBoundModifier::None => {}
876                    TraitBoundModifier::Maybe(maybe) => {
877                        let msg = "`for<...>` binder not allowed with `?` trait polarity modifier";
878                        return Err(Error::new(maybe.span, msg));
879                    }
880                }
881            }
882
883            if is_conditionally_const || is_unconditionally_const {
884                Ok(None)
885            } else {
886                Ok(Some(TraitBound {
887                    paren_token: None,
888                    modifier,
889                    lifetimes,
890                    path,
891                }))
892            }
893        }
894    }
895
896    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
897    impl Parse for TraitBoundModifier {
898        fn parse(input: ParseStream) -> Result<Self> {
899            if input.peek(crate::token::QuestionToken![?]) {
900                input.parse().map(TraitBoundModifier::Maybe)
901            } else {
902                Ok(TraitBoundModifier::None)
903            }
904        }
905    }
906
907    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
908    impl Parse for ConstParam {
909        fn parse(input: ParseStream) -> Result<Self> {
910            let mut default = None;
911            Ok(ConstParam {
912                attrs: input.call(Attribute::parse_outer)?,
913                const_token: input.parse()?,
914                ident: input.parse()?,
915                colon_token: input.parse()?,
916                ty: input.parse()?,
917                eq_token: {
918                    if input.peek(crate::token::EqToken![=]) {
919                        let eq_token = input.parse()?;
920                        default = Some(path::parsing::const_argument(input)?);
921                        Some(eq_token)
922                    } else {
923                        None
924                    }
925                },
926                default,
927            })
928        }
929    }
930
931    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
932    impl Parse for WhereClause {
933        fn parse(input: ParseStream) -> Result<Self> {
934            let where_token: crate::token::WhereToken![where] = input.parse()?;
935
936            if choose_generics_over_qpath(input) {
937                return Err(input
938                    .error("generic parameters on `where` clauses are reserved for future use"));
939            }
940
941            Ok(WhereClause {
942                where_token,
943                predicates: {
944                    let mut predicates = Punctuated::new();
945                    loop {
946                        if input.is_empty()
947                            || input.peek(token::Brace)
948                            || input.peek(crate::token::CommaToken![,])
949                            || input.peek(crate::token::SemiToken![;])
950                            || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
951                            || input.peek(crate::token::EqToken![=])
952                        {
953                            break;
954                        }
955                        let value = input.parse()?;
956                        predicates.push_value(value);
957                        if !input.peek(crate::token::CommaToken![,]) {
958                            break;
959                        }
960                        let punct = input.parse()?;
961                        predicates.push_punct(punct);
962                    }
963                    predicates
964                },
965            })
966        }
967    }
968
969    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
970    impl Parse for Option<WhereClause> {
971        fn parse(input: ParseStream) -> Result<Self> {
972            if input.peek(crate::token::WhereToken![where]) {
973                input.parse().map(Some)
974            } else {
975                Ok(None)
976            }
977        }
978    }
979
980    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
981    impl Parse for WherePredicate {
982        fn parse(input: ParseStream) -> Result<Self> {
983            if input.peek(Lifetime) && input.peek2(crate::token::ColonToken![:]) {
984                Ok(WherePredicate::Lifetime(PredicateLifetime {
985                    lifetime: input.parse()?,
986                    colon_token: input.parse()?,
987                    bounds: {
988                        let mut bounds = Punctuated::new();
989                        loop {
990                            if input.is_empty()
991                                || input.peek(token::Brace)
992                                || input.peek(crate::token::CommaToken![,])
993                                || input.peek(crate::token::SemiToken![;])
994                                || input.peek(crate::token::ColonToken![:])
995                                || input.peek(crate::token::EqToken![=])
996                            {
997                                break;
998                            }
999                            let value = input.parse()?;
1000                            bounds.push_value(value);
1001                            if !input.peek(crate::token::PlusToken![+]) {
1002                                break;
1003                            }
1004                            let punct = input.parse()?;
1005                            bounds.push_punct(punct);
1006                        }
1007                        bounds
1008                    },
1009                }))
1010            } else {
1011                Ok(WherePredicate::Type(PredicateType {
1012                    lifetimes: input.parse()?,
1013                    bounded_ty: input.parse()?,
1014                    colon_token: input.parse()?,
1015                    bounds: {
1016                        let mut bounds = Punctuated::new();
1017                        loop {
1018                            if input.is_empty()
1019                                || input.peek(token::Brace)
1020                                || input.peek(crate::token::CommaToken![,])
1021                                || input.peek(crate::token::SemiToken![;])
1022                                || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
1023                                || input.peek(crate::token::EqToken![=])
1024                            {
1025                                break;
1026                            }
1027                            bounds.push_value({
1028                                let allow_precise_capture = false;
1029                                let allow_const = true;
1030                                TypeParamBound::parse_single(
1031                                    input,
1032                                    allow_precise_capture,
1033                                    allow_const,
1034                                )?
1035                            });
1036                            if !input.peek(crate::token::PlusToken![+]) {
1037                                break;
1038                            }
1039                            let punct = input.parse()?;
1040                            bounds.push_punct(punct);
1041                        }
1042                        bounds
1043                    },
1044                }))
1045            }
1046        }
1047    }
1048
1049    #[cfg(feature = "full")]
1050    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1051    impl Parse for PreciseCapture {
1052        fn parse(input: ParseStream) -> Result<Self> {
1053            let use_token: crate::token::UseToken![use] = input.parse()?;
1054            let lt_token: crate::token::LtToken![<] = input.parse()?;
1055            let mut params = Punctuated::new();
1056            loop {
1057                let lookahead = input.lookahead1();
1058                params.push_value(
1059                    if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(crate::token::SelfTypeToken![Self])
1060                    {
1061                        input.parse::<CapturedParam>()?
1062                    } else if lookahead.peek(crate::token::GtToken![>]) {
1063                        break;
1064                    } else {
1065                        return Err(lookahead.error());
1066                    },
1067                );
1068                let lookahead = input.lookahead1();
1069                params.push_punct(if lookahead.peek(crate::token::CommaToken![,]) {
1070                    input.parse::<crate::token::CommaToken![,]>()?
1071                } else if lookahead.peek(crate::token::GtToken![>]) {
1072                    break;
1073                } else {
1074                    return Err(lookahead.error());
1075                });
1076            }
1077            let gt_token: crate::token::GtToken![>] = input.parse()?;
1078            Ok(PreciseCapture {
1079                use_token,
1080                lt_token,
1081                params,
1082                gt_token,
1083            })
1084        }
1085    }
1086
1087    #[cfg(feature = "full")]
1088    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1089    impl Parse for CapturedParam {
1090        fn parse(input: ParseStream) -> Result<Self> {
1091            let lookahead = input.lookahead1();
1092            if lookahead.peek(Lifetime) {
1093                input.parse().map(CapturedParam::Lifetime)
1094            } else if lookahead.peek(Ident) || input.peek(crate::token::SelfTypeToken![Self]) {
1095                input.call(Ident::parse_any).map(CapturedParam::Ident)
1096            } else {
1097                Err(lookahead.error())
1098            }
1099        }
1100    }
1101
1102    pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool {
1103        // Rust syntax has an ambiguity between generic parameters and qualified
1104        // paths. In `impl <T> :: Thing<T, U> {}` this may either be a generic
1105        // inherent impl `impl<T> ::Thing<T, U>` or a non-generic inherent impl
1106        // for an associated type `impl <T>::Thing<T, U>`.
1107        //
1108        // After `<` the following continuations can only begin generics, not a
1109        // qualified path:
1110        //
1111        //     `<` `>`                  - empty generic parameters
1112        //     `<` `#`                  - generic parameters with attribute
1113        //     `<` LIFETIME `>`         - single lifetime parameter
1114        //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
1115        //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
1116        //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
1117        //     `<` const                - generic const parameter
1118        //
1119        // The only truly ambiguous case is:
1120        //
1121        //     `<` IDENT `>` `::` IDENT ...
1122        //
1123        // which we disambiguate in favor of generics because this is almost
1124        // always the expected one in the context of real-world code.
1125        input.peek(crate::token::LtToken![<])
1126            && (input.peek2(crate::token::GtToken![>])
1127                || input.peek2(crate::token::PoundToken![#])
1128                || (input.peek2(Lifetime) || input.peek2(Ident))
1129                    && (input.peek3(crate::token::GtToken![>])
1130                        || input.peek3(crate::token::CommaToken![,])
1131                        || input.peek3(crate::token::ColonToken![:]) && !input.peek3(crate::token::PathSepToken![::])
1132                        || input.peek3(crate::token::EqToken![=]))
1133                || input.peek2(crate::token::ConstToken![const]))
1134    }
1135
1136    #[cfg(feature = "full")]
1137    pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool {
1138        let input = input.fork();
1139        input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where`
1140        choose_generics_over_qpath(&input)
1141    }
1142}
1143
1144#[cfg(feature = "printing")]
1145pub(crate) mod printing {
1146    use crate::attr::FilterAttrs;
1147    #[cfg(feature = "full")]
1148    use crate::expr;
1149    use crate::expr::Expr;
1150    #[cfg(feature = "full")]
1151    use crate::fixup::FixupContext;
1152    use crate::generics::{
1153        BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam,
1154        PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics,
1155        TypeParam, WhereClause,
1156    };
1157    #[cfg(feature = "full")]
1158    use crate::generics::{CapturedParam, PreciseCapture};
1159    use crate::print::TokensOrDefault;
1160    use crate::token;
1161    use proc_macro2::TokenStream;
1162    use quote::{ToTokens, TokenStreamExt as _};
1163
1164    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1165    impl ToTokens for Generics {
1166        fn to_tokens(&self, tokens: &mut TokenStream) {
1167            if self.params.is_empty() {
1168                return;
1169            }
1170
1171            TokensOrDefault(&self.lt_token).to_tokens(tokens);
1172
1173            // Print lifetimes before types and consts, regardless of their
1174            // order in self.params.
1175            let mut trailing_or_empty = true;
1176            for param in self.params.pairs() {
1177                if let GenericParam::Lifetime(_) = **param.value() {
1178                    param.to_tokens(tokens);
1179                    trailing_or_empty = param.punct().is_some();
1180                }
1181            }
1182            for param in self.params.pairs() {
1183                match param.value() {
1184                    GenericParam::Type(_) | GenericParam::Const(_) => {
1185                        if !trailing_or_empty {
1186                            <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1187                            trailing_or_empty = true;
1188                        }
1189                        param.to_tokens(tokens);
1190                    }
1191                    GenericParam::Lifetime(_) => {}
1192                }
1193            }
1194
1195            TokensOrDefault(&self.gt_token).to_tokens(tokens);
1196        }
1197    }
1198
1199    impl<'a> ToTokens for ImplGenerics<'a> {
1200        fn to_tokens(&self, tokens: &mut TokenStream) {
1201            if self.0.params.is_empty() {
1202                return;
1203            }
1204
1205            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1206
1207            // Print lifetimes before types and consts, regardless of their
1208            // order in self.params.
1209            let mut trailing_or_empty = true;
1210            for param in self.0.params.pairs() {
1211                if let GenericParam::Lifetime(_) = **param.value() {
1212                    param.to_tokens(tokens);
1213                    trailing_or_empty = param.punct().is_some();
1214                }
1215            }
1216            for param in self.0.params.pairs() {
1217                if let GenericParam::Lifetime(_) = **param.value() {
1218                    continue;
1219                }
1220                if !trailing_or_empty {
1221                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1222                    trailing_or_empty = true;
1223                }
1224                match param.value() {
1225                    GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1226                    GenericParam::Type(param) => {
1227                        // Leave off the type parameter defaults
1228                        tokens.append_all(param.attrs.outer());
1229                        param.ident.to_tokens(tokens);
1230                        if !param.bounds.is_empty() {
1231                            TokensOrDefault(&param.colon_token).to_tokens(tokens);
1232                            param.bounds.to_tokens(tokens);
1233                        }
1234                    }
1235                    GenericParam::Const(param) => {
1236                        // Leave off the const parameter defaults
1237                        tokens.append_all(param.attrs.outer());
1238                        param.const_token.to_tokens(tokens);
1239                        param.ident.to_tokens(tokens);
1240                        param.colon_token.to_tokens(tokens);
1241                        param.ty.to_tokens(tokens);
1242                    }
1243                }
1244                param.punct().to_tokens(tokens);
1245            }
1246
1247            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1248        }
1249    }
1250
1251    impl<'a> ToTokens for TypeGenerics<'a> {
1252        fn to_tokens(&self, tokens: &mut TokenStream) {
1253            if self.0.params.is_empty() {
1254                return;
1255            }
1256
1257            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1258
1259            // Print lifetimes before types and consts, regardless of their
1260            // order in self.params.
1261            let mut trailing_or_empty = true;
1262            for param in self.0.params.pairs() {
1263                if let GenericParam::Lifetime(def) = *param.value() {
1264                    // Leave off the lifetime bounds and attributes
1265                    def.lifetime.to_tokens(tokens);
1266                    param.punct().to_tokens(tokens);
1267                    trailing_or_empty = param.punct().is_some();
1268                }
1269            }
1270            for param in self.0.params.pairs() {
1271                if let GenericParam::Lifetime(_) = **param.value() {
1272                    continue;
1273                }
1274                if !trailing_or_empty {
1275                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1276                    trailing_or_empty = true;
1277                }
1278                match param.value() {
1279                    GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1280                    GenericParam::Type(param) => {
1281                        // Leave off the type parameter defaults
1282                        param.ident.to_tokens(tokens);
1283                    }
1284                    GenericParam::Const(param) => {
1285                        // Leave off the const parameter defaults
1286                        param.ident.to_tokens(tokens);
1287                    }
1288                }
1289                param.punct().to_tokens(tokens);
1290            }
1291
1292            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1293        }
1294    }
1295
1296    impl<'a> ToTokens for Turbofish<'a> {
1297        fn to_tokens(&self, tokens: &mut TokenStream) {
1298            if !self.0.params.is_empty() {
1299                <crate::token::PathSepToken![::]>::default().to_tokens(tokens);
1300                TypeGenerics(self.0).to_tokens(tokens);
1301            }
1302        }
1303    }
1304
1305    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1306    impl ToTokens for BoundLifetimes {
1307        fn to_tokens(&self, tokens: &mut TokenStream) {
1308            self.for_token.to_tokens(tokens);
1309            self.lt_token.to_tokens(tokens);
1310            self.lifetimes.to_tokens(tokens);
1311            self.gt_token.to_tokens(tokens);
1312        }
1313    }
1314
1315    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1316    impl ToTokens for LifetimeParam {
1317        fn to_tokens(&self, tokens: &mut TokenStream) {
1318            tokens.append_all(self.attrs.outer());
1319            self.lifetime.to_tokens(tokens);
1320            if !self.bounds.is_empty() {
1321                TokensOrDefault(&self.colon_token).to_tokens(tokens);
1322                self.bounds.to_tokens(tokens);
1323            }
1324        }
1325    }
1326
1327    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1328    impl ToTokens for TypeParam {
1329        fn to_tokens(&self, tokens: &mut TokenStream) {
1330            tokens.append_all(self.attrs.outer());
1331            self.ident.to_tokens(tokens);
1332            if !self.bounds.is_empty() {
1333                TokensOrDefault(&self.colon_token).to_tokens(tokens);
1334                self.bounds.to_tokens(tokens);
1335            }
1336            if let Some(default) = &self.default {
1337                TokensOrDefault(&self.eq_token).to_tokens(tokens);
1338                default.to_tokens(tokens);
1339            }
1340        }
1341    }
1342
1343    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1344    impl ToTokens for TraitBound {
1345        fn to_tokens(&self, tokens: &mut TokenStream) {
1346            let to_tokens = |tokens: &mut TokenStream| {
1347                self.modifier.to_tokens(tokens);
1348                self.lifetimes.to_tokens(tokens);
1349                self.path.to_tokens(tokens);
1350            };
1351            match &self.paren_token {
1352                Some(paren) => paren.surround(tokens, to_tokens),
1353                None => to_tokens(tokens),
1354            }
1355        }
1356    }
1357
1358    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1359    impl ToTokens for TraitBoundModifier {
1360        fn to_tokens(&self, tokens: &mut TokenStream) {
1361            match self {
1362                TraitBoundModifier::None => {}
1363                TraitBoundModifier::Maybe(t) => t.to_tokens(tokens),
1364            }
1365        }
1366    }
1367
1368    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1369    impl ToTokens for ConstParam {
1370        fn to_tokens(&self, tokens: &mut TokenStream) {
1371            tokens.append_all(self.attrs.outer());
1372            self.const_token.to_tokens(tokens);
1373            self.ident.to_tokens(tokens);
1374            self.colon_token.to_tokens(tokens);
1375            self.ty.to_tokens(tokens);
1376            if let Some(default) = &self.default {
1377                TokensOrDefault(&self.eq_token).to_tokens(tokens);
1378                print_const_argument(default, tokens);
1379            }
1380        }
1381    }
1382
1383    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1384    impl ToTokens for WhereClause {
1385        fn to_tokens(&self, tokens: &mut TokenStream) {
1386            if !self.predicates.is_empty() {
1387                self.where_token.to_tokens(tokens);
1388                self.predicates.to_tokens(tokens);
1389            }
1390        }
1391    }
1392
1393    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1394    impl ToTokens for PredicateLifetime {
1395        fn to_tokens(&self, tokens: &mut TokenStream) {
1396            self.lifetime.to_tokens(tokens);
1397            self.colon_token.to_tokens(tokens);
1398            self.bounds.to_tokens(tokens);
1399        }
1400    }
1401
1402    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1403    impl ToTokens for PredicateType {
1404        fn to_tokens(&self, tokens: &mut TokenStream) {
1405            self.lifetimes.to_tokens(tokens);
1406            self.bounded_ty.to_tokens(tokens);
1407            self.colon_token.to_tokens(tokens);
1408            self.bounds.to_tokens(tokens);
1409        }
1410    }
1411
1412    #[cfg(feature = "full")]
1413    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1414    impl ToTokens for PreciseCapture {
1415        fn to_tokens(&self, tokens: &mut TokenStream) {
1416            self.use_token.to_tokens(tokens);
1417            self.lt_token.to_tokens(tokens);
1418
1419            // Print lifetimes before types and consts, regardless of their
1420            // order in self.params.
1421            let mut trailing_or_empty = true;
1422            for param in self.params.pairs() {
1423                if let CapturedParam::Lifetime(_) = **param.value() {
1424                    param.to_tokens(tokens);
1425                    trailing_or_empty = param.punct().is_some();
1426                }
1427            }
1428            for param in self.params.pairs() {
1429                if let CapturedParam::Ident(_) = **param.value() {
1430                    if !trailing_or_empty {
1431                        <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1432                        trailing_or_empty = true;
1433                    }
1434                    param.to_tokens(tokens);
1435                }
1436            }
1437
1438            self.gt_token.to_tokens(tokens);
1439        }
1440    }
1441
1442    #[cfg(feature = "full")]
1443    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1444    impl ToTokens for CapturedParam {
1445        fn to_tokens(&self, tokens: &mut TokenStream) {
1446            match self {
1447                CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
1448                CapturedParam::Ident(ident) => ident.to_tokens(tokens),
1449            }
1450        }
1451    }
1452
1453    pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) {
1454        match expr {
1455            Expr::Lit(expr) => expr.to_tokens(tokens),
1456
1457            Expr::Path(expr)
1458                if expr.attrs.is_empty()
1459                    && expr.qself.is_none()
1460                    && expr.path.get_ident().is_some() =>
1461            {
1462                expr.to_tokens(tokens);
1463            }
1464
1465            #[cfg(feature = "full")]
1466            Expr::Block(expr) => expr.to_tokens(tokens),
1467
1468            #[cfg(not(feature = "full"))]
1469            Expr::Verbatim(expr) => expr.to_tokens(tokens),
1470
1471            // ERROR CORRECTION: Add braces to make sure that the
1472            // generated code is valid.
1473            _ => token::Brace::default().surround(tokens, |tokens| {
1474                #[cfg(feature = "full")]
1475                expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
1476
1477                #[cfg(not(feature = "full"))]
1478                expr.to_tokens(tokens);
1479            }),
1480        }
1481    }
1482}