syn/
generics.rs

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