Skip to main content

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"]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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"]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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) }
}
#[doc(cfg(feature = "printing"))]
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`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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>`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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    #[doc = r" Iterator over the lifetime parameters in `self.params`."]
pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> {
    Lifetimes(self.params.iter())
}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    #[doc = r" Iterator over the lifetime parameters in `self.params`."]
pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> {
    LifetimesMut(self.params.iter_mut())
}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    #[doc = r" Iterator over the type parameters in `self.params`."]
pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> {
    TypeParams(self.params.iter())
}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    #[doc = r" Iterator over the type parameters in `self.params`."]
pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> {
    TypeParamsMut(self.params.iter_mut())
}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    #[doc = r" Iterator over the constant parameters in `self.params`."]
pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> {
    ConstParams(self.params.iter())
}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    #[doc = r" Iterator over the constant parameters in `self.params`."]
pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> {
    ConstParamsMut(self.params.iter_mut())
}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")]
339#[doc(cfg(feature = "clone-impls"))]
impl<'a> Clone for ImplGenerics<'a> {
    fn clone(&self) -> Self { ImplGenerics(self.0) }
}
#[doc(cfg(feature = "extra-traits"))]
impl<'a> Debug for ImplGenerics<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("ImplGenerics").field(self.0).finish()
    }
}
#[doc(cfg(feature = "extra-traits"))]
impl<'a> Eq for ImplGenerics<'a> { }
#[doc(cfg(feature = "extra-traits"))]
impl<'a> PartialEq for ImplGenerics<'a> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
#[doc(cfg(feature = "extra-traits"))]
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")]
341#[doc(cfg(feature = "clone-impls"))]
impl<'a> Clone for TypeGenerics<'a> {
    fn clone(&self) -> Self { TypeGenerics(self.0) }
}
#[doc(cfg(feature = "extra-traits"))]
impl<'a> Debug for TypeGenerics<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("TypeGenerics").field(self.0).finish()
    }
}
#[doc(cfg(feature = "extra-traits"))]
impl<'a> Eq for TypeGenerics<'a> { }
#[doc(cfg(feature = "extra-traits"))]
impl<'a> PartialEq for TypeGenerics<'a> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
#[doc(cfg(feature = "extra-traits"))]
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")]
343#[doc(cfg(feature = "clone-impls"))]
impl<'a> Clone for Turbofish<'a> {
    fn clone(&self) -> Self { Turbofish(self.0) }
}
#[doc(cfg(feature = "extra-traits"))]
impl<'a> Debug for Turbofish<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.debug_tuple("Turbofish").field(self.0).finish()
    }
}
#[doc(cfg(feature = "extra-traits"))]
impl<'a> Eq for Turbofish<'a> { }
#[doc(cfg(feature = "extra-traits"))]
impl<'a> PartialEq for Turbofish<'a> {
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}
#[doc(cfg(feature = "extra-traits"))]
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>`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
#[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)
    }
}
#[doc(cfg(feature = "printing"))]
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."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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>`."]
#[doc(cfg(feature = "full"))]
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."]
#[doc(cfg(feature = "full"))]
#[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`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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"]
#[doc(cfg(any(feature = "full", feature = "derive")))]
#[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) }
}
#[doc(cfg(feature = "printing"))]
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`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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>`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
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.cursor();
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(
797                    begin,
798                    input.cursor(),
799                )))
800            }
801        }
802
803        pub(crate) fn parse_multiple(
804            input: ParseStream,
805            allow_plus: bool,
806            allow_precise_capture: bool,
807            allow_const: bool,
808        ) -> Result<Punctuated<Self, crate::token::PlusToken![+]>> {
809            let mut bounds = Punctuated::new();
810            loop {
811                let bound = Self::parse_single(input, allow_precise_capture, allow_const)?;
812                bounds.push_value(bound);
813                if !(allow_plus && input.peek(crate::token::PlusToken![+])) {
814                    break;
815                }
816                bounds.push_punct(input.parse()?);
817                if !(input.peek(Ident::peek_any)
818                    || input.peek(crate::token::PathSepToken![::])
819                    || input.peek(crate::token::QuestionToken![?])
820                    || input.peek(Lifetime)
821                    || input.peek(token::Paren)
822                    || (allow_const && (input.peek(token::Bracket) || input.peek(crate::token::ConstToken![const]))))
823                {
824                    break;
825                }
826            }
827            Ok(bounds)
828        }
829    }
830
831    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
832    impl Parse for TraitBound {
833        fn parse(input: ParseStream) -> Result<Self> {
834            let allow_const = false;
835            Self::do_parse(input, allow_const).map(Option::unwrap)
836        }
837    }
838
839    impl TraitBound {
840        fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> {
841            let mut lifetimes: Option<BoundLifetimes> = input.parse()?;
842
843            let is_conditionally_const = truecfg!(feature = "full") && input.peek(token::Bracket);
844            let is_unconditionally_const = truecfg!(feature = "full") && input.peek(crate::token::ConstToken![const]);
845            if is_conditionally_const {
846                let conditionally_const;
847                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);
848                conditionally_const.parse::<crate::token::ConstToken![const]>()?;
849                if !allow_const {
850                    let msg = "`[const]` is not allowed here";
851                    return Err(Error::new(bracket_token.span.join(), msg));
852                }
853            } else if is_unconditionally_const {
854                let const_token: crate::token::ConstToken![const] = input.parse()?;
855                if !allow_const {
856                    let msg = "`const` is not allowed here";
857                    return Err(Error::new(const_token.span, msg));
858                }
859            }
860
861            let modifier: TraitBoundModifier = input.parse()?;
862            if lifetimes.is_none() && #[allow(non_exhaustive_omitted_patterns)] match modifier {
    TraitBoundModifier::Maybe(_) => true,
    _ => false,
}matches!(modifier, TraitBoundModifier::Maybe(_)) {
863                lifetimes = input.parse()?;
864            }
865
866            let mut path: Path = input.parse()?;
867            if path.segments.last().unwrap().arguments.is_empty()
868                && (input.peek(token::Paren) || input.peek(crate::token::PathSepToken![::]) && input.peek3(token::Paren))
869            {
870                input.parse::<Option<crate::token::PathSepToken![::]>>()?;
871                let args: ParenthesizedGenericArguments = input.parse()?;
872                let parenthesized = PathArguments::Parenthesized(args);
873                path.segments.last_mut().unwrap().arguments = parenthesized;
874            }
875
876            if lifetimes.is_some() {
877                match modifier {
878                    TraitBoundModifier::None => {}
879                    TraitBoundModifier::Maybe(maybe) => {
880                        let msg = "`for<...>` binder not allowed with `?` trait polarity modifier";
881                        return Err(Error::new(maybe.span, msg));
882                    }
883                }
884            }
885
886            if is_conditionally_const || is_unconditionally_const {
887                Ok(None)
888            } else {
889                Ok(Some(TraitBound {
890                    paren_token: None,
891                    modifier,
892                    lifetimes,
893                    path,
894                }))
895            }
896        }
897    }
898
899    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
900    impl Parse for TraitBoundModifier {
901        fn parse(input: ParseStream) -> Result<Self> {
902            if input.peek(crate::token::QuestionToken![?]) {
903                input.parse().map(TraitBoundModifier::Maybe)
904            } else {
905                Ok(TraitBoundModifier::None)
906            }
907        }
908    }
909
910    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
911    impl Parse for ConstParam {
912        fn parse(input: ParseStream) -> Result<Self> {
913            let mut default = None;
914            Ok(ConstParam {
915                attrs: input.call(Attribute::parse_outer)?,
916                const_token: input.parse()?,
917                ident: input.parse()?,
918                colon_token: input.parse()?,
919                ty: input.parse()?,
920                eq_token: {
921                    if input.peek(crate::token::EqToken![=]) {
922                        let eq_token = input.parse()?;
923                        default = Some(path::parsing::const_argument(input)?);
924                        Some(eq_token)
925                    } else {
926                        None
927                    }
928                },
929                default,
930            })
931        }
932    }
933
934    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
935    impl Parse for WhereClause {
936        fn parse(input: ParseStream) -> Result<Self> {
937            let where_token: crate::token::WhereToken![where] = input.parse()?;
938
939            if choose_generics_over_qpath(input) {
940                return Err(input
941                    .error("generic parameters on `where` clauses are reserved for future use"));
942            }
943
944            Ok(WhereClause {
945                where_token,
946                predicates: {
947                    let mut predicates = Punctuated::new();
948                    loop {
949                        if input.is_empty()
950                            || input.peek(token::Brace)
951                            || input.peek(crate::token::CommaToken![,])
952                            || input.peek(crate::token::SemiToken![;])
953                            || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
954                            || input.peek(crate::token::EqToken![=])
955                        {
956                            break;
957                        }
958                        let value = input.parse()?;
959                        predicates.push_value(value);
960                        if !input.peek(crate::token::CommaToken![,]) {
961                            break;
962                        }
963                        let punct = input.parse()?;
964                        predicates.push_punct(punct);
965                    }
966                    predicates
967                },
968            })
969        }
970    }
971
972    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
973    impl Parse for Option<WhereClause> {
974        fn parse(input: ParseStream) -> Result<Self> {
975            if input.peek(crate::token::WhereToken![where]) {
976                input.parse().map(Some)
977            } else {
978                Ok(None)
979            }
980        }
981    }
982
983    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
984    impl Parse for WherePredicate {
985        fn parse(input: ParseStream) -> Result<Self> {
986            if input.peek(Lifetime) && input.peek2(crate::token::ColonToken![:]) {
987                Ok(WherePredicate::Lifetime(PredicateLifetime {
988                    lifetime: input.parse()?,
989                    colon_token: input.parse()?,
990                    bounds: {
991                        let mut bounds = Punctuated::new();
992                        loop {
993                            if input.is_empty()
994                                || input.peek(token::Brace)
995                                || input.peek(crate::token::CommaToken![,])
996                                || input.peek(crate::token::SemiToken![;])
997                                || input.peek(crate::token::ColonToken![:])
998                                || input.peek(crate::token::EqToken![=])
999                            {
1000                                break;
1001                            }
1002                            let value = input.parse()?;
1003                            bounds.push_value(value);
1004                            if !input.peek(crate::token::PlusToken![+]) {
1005                                break;
1006                            }
1007                            let punct = input.parse()?;
1008                            bounds.push_punct(punct);
1009                        }
1010                        bounds
1011                    },
1012                }))
1013            } else {
1014                Ok(WherePredicate::Type(PredicateType {
1015                    lifetimes: input.parse()?,
1016                    bounded_ty: input.parse()?,
1017                    colon_token: input.parse()?,
1018                    bounds: {
1019                        let mut bounds = Punctuated::new();
1020                        loop {
1021                            if input.is_empty()
1022                                || input.peek(token::Brace)
1023                                || input.peek(crate::token::CommaToken![,])
1024                                || input.peek(crate::token::SemiToken![;])
1025                                || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
1026                                || input.peek(crate::token::EqToken![=])
1027                            {
1028                                break;
1029                            }
1030                            bounds.push_value({
1031                                let allow_precise_capture = false;
1032                                let allow_const = true;
1033                                TypeParamBound::parse_single(
1034                                    input,
1035                                    allow_precise_capture,
1036                                    allow_const,
1037                                )?
1038                            });
1039                            if !input.peek(crate::token::PlusToken![+]) {
1040                                break;
1041                            }
1042                            let punct = input.parse()?;
1043                            bounds.push_punct(punct);
1044                        }
1045                        bounds
1046                    },
1047                }))
1048            }
1049        }
1050    }
1051
1052    #[cfg(feature = "full")]
1053    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1054    impl Parse for PreciseCapture {
1055        fn parse(input: ParseStream) -> Result<Self> {
1056            let use_token: crate::token::UseToken![use] = input.parse()?;
1057            let lt_token: crate::token::LtToken![<] = input.parse()?;
1058            let mut params = Punctuated::new();
1059            loop {
1060                let lookahead = input.lookahead1();
1061                params.push_value(
1062                    if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(crate::token::SelfTypeToken![Self])
1063                    {
1064                        input.parse::<CapturedParam>()?
1065                    } else if lookahead.peek(crate::token::GtToken![>]) {
1066                        break;
1067                    } else {
1068                        return Err(lookahead.error());
1069                    },
1070                );
1071                let lookahead = input.lookahead1();
1072                params.push_punct(if lookahead.peek(crate::token::CommaToken![,]) {
1073                    input.parse::<crate::token::CommaToken![,]>()?
1074                } else if lookahead.peek(crate::token::GtToken![>]) {
1075                    break;
1076                } else {
1077                    return Err(lookahead.error());
1078                });
1079            }
1080            let gt_token: crate::token::GtToken![>] = input.parse()?;
1081            Ok(PreciseCapture {
1082                use_token,
1083                lt_token,
1084                params,
1085                gt_token,
1086            })
1087        }
1088    }
1089
1090    #[cfg(feature = "full")]
1091    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1092    impl Parse for CapturedParam {
1093        fn parse(input: ParseStream) -> Result<Self> {
1094            let lookahead = input.lookahead1();
1095            if lookahead.peek(Lifetime) {
1096                input.parse().map(CapturedParam::Lifetime)
1097            } else if lookahead.peek(Ident) || input.peek(crate::token::SelfTypeToken![Self]) {
1098                input.call(Ident::parse_any).map(CapturedParam::Ident)
1099            } else {
1100                Err(lookahead.error())
1101            }
1102        }
1103    }
1104
1105    pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool {
1106        // Rust syntax has an ambiguity between generic parameters and qualified
1107        // paths. In `impl <T> :: Thing<T, U> {}` this may either be a generic
1108        // inherent impl `impl<T> ::Thing<T, U>` or a non-generic inherent impl
1109        // for an associated type `impl <T>::Thing<T, U>`.
1110        //
1111        // After `<` the following continuations can only begin generics, not a
1112        // qualified path:
1113        //
1114        //     `<` `>`                  - empty generic parameters
1115        //     `<` `#`                  - generic parameters with attribute
1116        //     `<` LIFETIME `>`         - single lifetime parameter
1117        //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
1118        //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
1119        //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
1120        //     `<` const                - generic const parameter
1121        //
1122        // The only truly ambiguous case is:
1123        //
1124        //     `<` IDENT `>` `::` IDENT ...
1125        //
1126        // which we disambiguate in favor of generics because this is almost
1127        // always the expected one in the context of real-world code.
1128        input.peek(crate::token::LtToken![<])
1129            && (input.peek2(crate::token::GtToken![>])
1130                || input.peek2(crate::token::PoundToken![#])
1131                || (input.peek2(Lifetime) || input.peek2(Ident))
1132                    && (input.peek3(crate::token::GtToken![>])
1133                        || input.peek3(crate::token::CommaToken![,])
1134                        || input.peek3(crate::token::ColonToken![:]) && !input.peek3(crate::token::PathSepToken![::])
1135                        || input.peek3(crate::token::EqToken![=]))
1136                || input.peek2(crate::token::ConstToken![const]))
1137    }
1138
1139    #[cfg(feature = "full")]
1140    pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool {
1141        let input = input.fork();
1142        input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where`
1143        choose_generics_over_qpath(&input)
1144    }
1145}
1146
1147#[cfg(feature = "printing")]
1148pub(crate) mod printing {
1149    use crate::attr::FilterAttrs;
1150    #[cfg(feature = "full")]
1151    use crate::expr;
1152    use crate::expr::Expr;
1153    #[cfg(feature = "full")]
1154    use crate::fixup::FixupContext;
1155    use crate::generics::{
1156        BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam,
1157        PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics,
1158        TypeParam, WhereClause,
1159    };
1160    #[cfg(feature = "full")]
1161    use crate::generics::{CapturedParam, PreciseCapture};
1162    use crate::print::TokensOrDefault;
1163    use crate::token;
1164    use proc_macro2::TokenStream;
1165    use quote::{ToTokens, TokenStreamExt as _};
1166
1167    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1168    impl ToTokens for Generics {
1169        fn to_tokens(&self, tokens: &mut TokenStream) {
1170            if self.params.is_empty() {
1171                return;
1172            }
1173
1174            TokensOrDefault(&self.lt_token).to_tokens(tokens);
1175
1176            // Print lifetimes before types and consts, regardless of their
1177            // order in self.params.
1178            let mut trailing_or_empty = true;
1179            for param in self.params.pairs() {
1180                if let GenericParam::Lifetime(_) = **param.value() {
1181                    param.to_tokens(tokens);
1182                    trailing_or_empty = param.punct().is_some();
1183                }
1184            }
1185            for param in self.params.pairs() {
1186                match param.value() {
1187                    GenericParam::Type(_) | GenericParam::Const(_) => {
1188                        if !trailing_or_empty {
1189                            <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1190                            trailing_or_empty = true;
1191                        }
1192                        param.to_tokens(tokens);
1193                    }
1194                    GenericParam::Lifetime(_) => {}
1195                }
1196            }
1197
1198            TokensOrDefault(&self.gt_token).to_tokens(tokens);
1199        }
1200    }
1201
1202    impl<'a> ToTokens for ImplGenerics<'a> {
1203        fn to_tokens(&self, tokens: &mut TokenStream) {
1204            if self.0.params.is_empty() {
1205                return;
1206            }
1207
1208            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1209
1210            // Print lifetimes before types and consts, regardless of their
1211            // order in self.params.
1212            let mut trailing_or_empty = true;
1213            for param in self.0.params.pairs() {
1214                if let GenericParam::Lifetime(_) = **param.value() {
1215                    param.to_tokens(tokens);
1216                    trailing_or_empty = param.punct().is_some();
1217                }
1218            }
1219            for param in self.0.params.pairs() {
1220                if let GenericParam::Lifetime(_) = **param.value() {
1221                    continue;
1222                }
1223                if !trailing_or_empty {
1224                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1225                    trailing_or_empty = true;
1226                }
1227                match param.value() {
1228                    GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1229                    GenericParam::Type(param) => {
1230                        // Leave off the type parameter defaults
1231                        tokens.append_all(param.attrs.outer());
1232                        param.ident.to_tokens(tokens);
1233                        if !param.bounds.is_empty() {
1234                            TokensOrDefault(&param.colon_token).to_tokens(tokens);
1235                            param.bounds.to_tokens(tokens);
1236                        }
1237                    }
1238                    GenericParam::Const(param) => {
1239                        // Leave off the const parameter defaults
1240                        tokens.append_all(param.attrs.outer());
1241                        param.const_token.to_tokens(tokens);
1242                        param.ident.to_tokens(tokens);
1243                        param.colon_token.to_tokens(tokens);
1244                        param.ty.to_tokens(tokens);
1245                    }
1246                }
1247                param.punct().to_tokens(tokens);
1248            }
1249
1250            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1251        }
1252    }
1253
1254    impl<'a> ToTokens for TypeGenerics<'a> {
1255        fn to_tokens(&self, tokens: &mut TokenStream) {
1256            if self.0.params.is_empty() {
1257                return;
1258            }
1259
1260            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1261
1262            // Print lifetimes before types and consts, regardless of their
1263            // order in self.params.
1264            let mut trailing_or_empty = true;
1265            for param in self.0.params.pairs() {
1266                if let GenericParam::Lifetime(def) = *param.value() {
1267                    // Leave off the lifetime bounds and attributes
1268                    def.lifetime.to_tokens(tokens);
1269                    param.punct().to_tokens(tokens);
1270                    trailing_or_empty = param.punct().is_some();
1271                }
1272            }
1273            for param in self.0.params.pairs() {
1274                if let GenericParam::Lifetime(_) = **param.value() {
1275                    continue;
1276                }
1277                if !trailing_or_empty {
1278                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1279                    trailing_or_empty = true;
1280                }
1281                match param.value() {
1282                    GenericParam::Lifetime(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1283                    GenericParam::Type(param) => {
1284                        // Leave off the type parameter defaults
1285                        param.ident.to_tokens(tokens);
1286                    }
1287                    GenericParam::Const(param) => {
1288                        // Leave off the const parameter defaults
1289                        param.ident.to_tokens(tokens);
1290                    }
1291                }
1292                param.punct().to_tokens(tokens);
1293            }
1294
1295            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1296        }
1297    }
1298
1299    impl<'a> ToTokens for Turbofish<'a> {
1300        fn to_tokens(&self, tokens: &mut TokenStream) {
1301            if !self.0.params.is_empty() {
1302                <crate::token::PathSepToken![::]>::default().to_tokens(tokens);
1303                TypeGenerics(self.0).to_tokens(tokens);
1304            }
1305        }
1306    }
1307
1308    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1309    impl ToTokens for BoundLifetimes {
1310        fn to_tokens(&self, tokens: &mut TokenStream) {
1311            self.for_token.to_tokens(tokens);
1312            self.lt_token.to_tokens(tokens);
1313            self.lifetimes.to_tokens(tokens);
1314            self.gt_token.to_tokens(tokens);
1315        }
1316    }
1317
1318    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1319    impl ToTokens for LifetimeParam {
1320        fn to_tokens(&self, tokens: &mut TokenStream) {
1321            tokens.append_all(self.attrs.outer());
1322            self.lifetime.to_tokens(tokens);
1323            if !self.bounds.is_empty() {
1324                TokensOrDefault(&self.colon_token).to_tokens(tokens);
1325                self.bounds.to_tokens(tokens);
1326            }
1327        }
1328    }
1329
1330    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1331    impl ToTokens for TypeParam {
1332        fn to_tokens(&self, tokens: &mut TokenStream) {
1333            tokens.append_all(self.attrs.outer());
1334            self.ident.to_tokens(tokens);
1335            if !self.bounds.is_empty() {
1336                TokensOrDefault(&self.colon_token).to_tokens(tokens);
1337                self.bounds.to_tokens(tokens);
1338            }
1339            if let Some(default) = &self.default {
1340                TokensOrDefault(&self.eq_token).to_tokens(tokens);
1341                default.to_tokens(tokens);
1342            }
1343        }
1344    }
1345
1346    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1347    impl ToTokens for TraitBound {
1348        fn to_tokens(&self, tokens: &mut TokenStream) {
1349            let to_tokens = |tokens: &mut TokenStream| {
1350                self.modifier.to_tokens(tokens);
1351                self.lifetimes.to_tokens(tokens);
1352                self.path.to_tokens(tokens);
1353            };
1354            match &self.paren_token {
1355                Some(paren) => paren.surround(tokens, to_tokens),
1356                None => to_tokens(tokens),
1357            }
1358        }
1359    }
1360
1361    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1362    impl ToTokens for TraitBoundModifier {
1363        fn to_tokens(&self, tokens: &mut TokenStream) {
1364            match self {
1365                TraitBoundModifier::None => {}
1366                TraitBoundModifier::Maybe(t) => t.to_tokens(tokens),
1367            }
1368        }
1369    }
1370
1371    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1372    impl ToTokens for ConstParam {
1373        fn to_tokens(&self, tokens: &mut TokenStream) {
1374            tokens.append_all(self.attrs.outer());
1375            self.const_token.to_tokens(tokens);
1376            self.ident.to_tokens(tokens);
1377            self.colon_token.to_tokens(tokens);
1378            self.ty.to_tokens(tokens);
1379            if let Some(default) = &self.default {
1380                TokensOrDefault(&self.eq_token).to_tokens(tokens);
1381                print_const_argument(default, tokens);
1382            }
1383        }
1384    }
1385
1386    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1387    impl ToTokens for WhereClause {
1388        fn to_tokens(&self, tokens: &mut TokenStream) {
1389            if !self.predicates.is_empty() {
1390                self.where_token.to_tokens(tokens);
1391                self.predicates.to_tokens(tokens);
1392            }
1393        }
1394    }
1395
1396    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1397    impl ToTokens for PredicateLifetime {
1398        fn to_tokens(&self, tokens: &mut TokenStream) {
1399            self.lifetime.to_tokens(tokens);
1400            self.colon_token.to_tokens(tokens);
1401            self.bounds.to_tokens(tokens);
1402        }
1403    }
1404
1405    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1406    impl ToTokens for PredicateType {
1407        fn to_tokens(&self, tokens: &mut TokenStream) {
1408            self.lifetimes.to_tokens(tokens);
1409            self.bounded_ty.to_tokens(tokens);
1410            self.colon_token.to_tokens(tokens);
1411            self.bounds.to_tokens(tokens);
1412        }
1413    }
1414
1415    #[cfg(feature = "full")]
1416    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1417    impl ToTokens for PreciseCapture {
1418        fn to_tokens(&self, tokens: &mut TokenStream) {
1419            self.use_token.to_tokens(tokens);
1420            self.lt_token.to_tokens(tokens);
1421
1422            // Print lifetimes before types and consts, regardless of their
1423            // order in self.params.
1424            let mut trailing_or_empty = true;
1425            for param in self.params.pairs() {
1426                if let CapturedParam::Lifetime(_) = **param.value() {
1427                    param.to_tokens(tokens);
1428                    trailing_or_empty = param.punct().is_some();
1429                }
1430            }
1431            for param in self.params.pairs() {
1432                if let CapturedParam::Ident(_) = **param.value() {
1433                    if !trailing_or_empty {
1434                        <crate::token::CommaToken![,]>::default().to_tokens(tokens);
1435                        trailing_or_empty = true;
1436                    }
1437                    param.to_tokens(tokens);
1438                }
1439            }
1440
1441            self.gt_token.to_tokens(tokens);
1442        }
1443    }
1444
1445    #[cfg(feature = "full")]
1446    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1447    impl ToTokens for CapturedParam {
1448        fn to_tokens(&self, tokens: &mut TokenStream) {
1449            match self {
1450                CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
1451                CapturedParam::Ident(ident) => ident.to_tokens(tokens),
1452            }
1453        }
1454    }
1455
1456    pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) {
1457        match expr {
1458            Expr::Lit(expr) => expr.to_tokens(tokens),
1459
1460            Expr::Path(expr)
1461                if expr.attrs.is_empty()
1462                    && expr.qself.is_none()
1463                    && expr.path.get_ident().is_some() =>
1464            {
1465                expr.to_tokens(tokens);
1466            }
1467
1468            #[cfg(feature = "full")]
1469            Expr::Block(expr) => expr.to_tokens(tokens),
1470
1471            #[cfg(not(feature = "full"))]
1472            Expr::Verbatim(expr) => expr.to_tokens(tokens),
1473
1474            // ERROR CORRECTION: Add braces to make sure that the
1475            // generated code is valid.
1476            _ => token::Brace::default().surround(tokens, |tokens| {
1477                #[cfg(feature = "full")]
1478                expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
1479
1480                #[cfg(not(feature = "full"))]
1481                expr.to_tokens(tokens);
1482            }),
1483        }
1484    }
1485}