Skip to main content

syn/
generics.rs

1use crate::attr::Attribute;
2#[cfg(feature = "parsing")]
3use crate::error::Result;
4use crate::expr::Expr;
5use crate::ident::Ident;
6use crate::lifetime::Lifetime;
7use crate::path::Path;
8use crate::punctuated::{Iter, IterMut, Punctuated};
9use crate::token;
10use crate::ty::Type;
11use alloc::vec::Vec;
12#[cfg(all(feature = "printing", feature = "extra-traits"))]
13use core::fmt::{self, Debug};
14#[cfg(all(feature = "printing", feature = "extra-traits"))]
15use core::hash::{Hash, Hasher};
16use proc_macro2::TokenStream;
17
18#[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! {
19    /// Lifetimes and type parameters attached to a declaration of a function,
20    /// enum, trait, etc.
21    ///
22    /// This struct represents two distinct optional syntactic elements,
23    /// [generic parameters] and [where clause]. In some locations of the
24    /// grammar, there may be other tokens in between these two things.
25    ///
26    /// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters
27    /// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses
28    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
29    pub struct Generics {
30        pub lt_token: Option<Token![<]>,
31        pub params: Punctuated<GenericParam, Token![,]>,
32        pub gt_token: Option<Token![>]>,
33        pub where_clause: Option<WhereClause>,
34    }
35}
36
37#[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 ::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! {
38    /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
39    /// `'a: 'b`, `const LEN: usize`.
40    ///
41    /// # Syntax tree enum
42    ///
43    /// This type is a [syntax tree enum].
44    ///
45    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
46    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
47    pub enum GenericParam {
48        /// A lifetime parameter: `'a: 'b + 'c + 'd`.
49        Lifetime(LifetimeParam),
50
51        /// A generic type parameter: `T: Into<String>`.
52        Type(TypeParam),
53
54        /// A const generic parameter: `const LENGTH: usize`.
55        Const(ConstParam),
56    }
57}
58
59#[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! {
60    /// A lifetime definition: `'a: 'b + 'c + 'd`.
61    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
62    pub struct LifetimeParam {
63        pub attrs: Vec<Attribute>,
64        pub lifetime: Lifetime,
65        pub colon_token: Option<Token![:]>,
66        pub bounds: Punctuated<Lifetime, Token![+]>,
67    }
68}
69
70#[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 default: Option<(crate::token::Eq, Type)>,
}ast_struct! {
71    /// A generic type parameter: `T: Into<String>`.
72    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
73    pub struct TypeParam {
74        pub attrs: Vec<Attribute>,
75        pub ident: Ident,
76        pub colon_token: Option<Token![:]>,
77        pub bounds: Punctuated<TypeParamBound, Token![+]>,
78        pub default: Option<(Token![=], Type)>,
79    }
80}
81
82#[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 default: Option<(crate::token::Eq, Expr)>,
}ast_struct! {
83    /// A const generic parameter: `const LENGTH: usize`.
84    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
85    pub struct ConstParam {
86        pub attrs: Vec<Attribute>,
87        pub const_token: Token![const],
88        pub ident: Ident,
89        pub colon_token: Token![:],
90        pub ty: Type,
91        pub default: Option<(Token![=], 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) -> Lifetimes { 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) -> LifetimesMut {
    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) -> TypeParams { 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) -> TypeParamsMut {
    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) -> ConstParams { 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) -> ConstParamsMut {
    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")]
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            default: None,
394        }
395    }
396}
397
398#[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),

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