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