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