Skip to main content

syn/
generics.rs

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