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