standalone_syn/
generics.rs

1// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use super::*;
10use punctuated::{Iter, IterMut, Punctuated};
11
12ast_struct! {
13    /// Lifetimes and type parameters attached to a declaration of a function,
14    /// enum, trait, etc.
15    ///
16    /// *This type is available if Syn is built with the `"derive"` or `"full"`
17    /// feature.*
18    #[derive(Default)]
19    pub struct Generics {
20        pub lt_token: Option<Token![<]>,
21        pub params: Punctuated<GenericParam, Token![,]>,
22        pub gt_token: Option<Token![>]>,
23        pub where_clause: Option<WhereClause>,
24    }
25}
26
27ast_enum_of_structs! {
28    /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
29    /// `'a: 'b`, `const LEN: usize`.
30    ///
31    /// *This type is available if Syn is built with the `"derive"` or `"full"`
32    /// feature.*
33    ///
34    /// # Syntax tree enum
35    ///
36    /// This type is a [syntax tree enum].
37    ///
38    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
39    pub enum GenericParam {
40        /// A generic type parameter: `T: Into<String>`.
41        ///
42        /// *This type is available if Syn is built with the `"derive"` or
43        /// `"full"` feature.*
44        pub Type(TypeParam {
45            pub attrs: Vec<Attribute>,
46            pub ident: Ident,
47            pub colon_token: Option<Token![:]>,
48            pub bounds: Punctuated<TypeParamBound, Token![+]>,
49            pub eq_token: Option<Token![=]>,
50            pub default: Option<Type>,
51        }),
52
53        /// A lifetime definition: `'a: 'b + 'c + 'd`.
54        ///
55        /// *This type is available if Syn is built with the `"derive"` or
56        /// `"full"` feature.*
57        pub Lifetime(LifetimeDef {
58            pub attrs: Vec<Attribute>,
59            pub lifetime: Lifetime,
60            pub colon_token: Option<Token![:]>,
61            pub bounds: Punctuated<Lifetime, Token![+]>,
62        }),
63
64        /// A const generic parameter: `const LENGTH: usize`.
65        ///
66        /// *This type is available if Syn is built with the `"derive"` or
67        /// `"full"` feature.*
68        pub Const(ConstParam {
69            pub attrs: Vec<Attribute>,
70            pub const_token: Token![const],
71            pub ident: Ident,
72            pub colon_token: Token![:],
73            pub ty: Type,
74            pub eq_token: Option<Token![=]>,
75            pub default: Option<Expr>,
76        }),
77    }
78}
79
80impl Generics {
81    /// Returns an
82    /// <code
83    ///   style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
84    ///   href="struct.TypeParam.html"><code
85    ///   style="padding-left:0;padding-right:0;">TypeParam</code></a><code
86    ///   style="padding-left:0;">&gt;</code>
87    /// over the type parameters in `self.params`.
88    pub fn type_params(&self) -> TypeParams {
89        TypeParams(self.params.iter())
90    }
91
92    /// Returns an
93    /// <code
94    ///   style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
95    ///   href="struct.TypeParam.html"><code
96    ///   style="padding-left:0;padding-right:0;">TypeParam</code></a><code
97    ///   style="padding-left:0;">&gt;</code>
98    /// over the type parameters in `self.params`.
99    pub fn type_params_mut(&mut self) -> TypeParamsMut {
100        TypeParamsMut(self.params.iter_mut())
101    }
102
103    /// Returns an
104    /// <code
105    ///   style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
106    ///   href="struct.LifetimeDef.html"><code
107    ///   style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
108    ///   style="padding-left:0;">&gt;</code>
109    /// over the lifetime parameters in `self.params`.
110    pub fn lifetimes(&self) -> Lifetimes {
111        Lifetimes(self.params.iter())
112    }
113
114    /// Returns an
115    /// <code
116    ///   style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
117    ///   href="struct.LifetimeDef.html"><code
118    ///   style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
119    ///   style="padding-left:0;">&gt;</code>
120    /// over the lifetime parameters in `self.params`.
121    pub fn lifetimes_mut(&mut self) -> LifetimesMut {
122        LifetimesMut(self.params.iter_mut())
123    }
124
125    /// Returns an
126    /// <code
127    ///   style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
128    ///   href="struct.ConstParam.html"><code
129    ///   style="padding-left:0;padding-right:0;">ConstParam</code></a><code
130    ///   style="padding-left:0;">&gt;</code>
131    /// over the constant parameters in `self.params`.
132    pub fn const_params(&self) -> ConstParams {
133        ConstParams(self.params.iter())
134    }
135
136    /// Returns an
137    /// <code
138    ///   style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
139    ///   href="struct.ConstParam.html"><code
140    ///   style="padding-left:0;padding-right:0;">ConstParam</code></a><code
141    ///   style="padding-left:0;">&gt;</code>
142    /// over the constant parameters in `self.params`.
143    pub fn const_params_mut(&mut self) -> ConstParamsMut {
144        ConstParamsMut(self.params.iter_mut())
145    }
146}
147
148pub struct TypeParams<'a>(Iter<'a, GenericParam, Token![,]>);
149
150impl<'a> Iterator for TypeParams<'a> {
151    type Item = &'a TypeParam;
152
153    fn next(&mut self) -> Option<Self::Item> {
154        // FIXME: Remove this when ? on Option is stable
155        let next = match self.0.next() {
156            Some(item) => item,
157            None => return None,
158        };
159        if let GenericParam::Type(ref type_param) = *next {
160            Some(type_param)
161        } else {
162            self.next()
163        }
164    }
165}
166
167pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam, Token![,]>);
168
169impl<'a> Iterator for TypeParamsMut<'a> {
170    type Item = &'a mut TypeParam;
171
172    fn next(&mut self) -> Option<Self::Item> {
173        // FIXME: Remove this when ? on Option is stable
174        let next = match self.0.next() {
175            Some(item) => item,
176            None => return None,
177        };
178        if let GenericParam::Type(ref mut type_param) = *next {
179            Some(type_param)
180        } else {
181            self.next()
182        }
183    }
184}
185
186pub struct Lifetimes<'a>(Iter<'a, GenericParam, Token![,]>);
187
188impl<'a> Iterator for Lifetimes<'a> {
189    type Item = &'a LifetimeDef;
190
191    fn next(&mut self) -> Option<Self::Item> {
192        // FIXME: Remove this when ? on Option is stable
193        let next = match self.0.next() {
194            Some(item) => item,
195            None => return None,
196        };
197        if let GenericParam::Lifetime(ref lifetime) = *next {
198            Some(lifetime)
199        } else {
200            self.next()
201        }
202    }
203}
204
205pub struct LifetimesMut<'a>(IterMut<'a, GenericParam, Token![,]>);
206
207impl<'a> Iterator for LifetimesMut<'a> {
208    type Item = &'a mut LifetimeDef;
209
210    fn next(&mut self) -> Option<Self::Item> {
211        // FIXME: Remove this when ? on Option is stable
212        let next = match self.0.next() {
213            Some(item) => item,
214            None => return None,
215        };
216        if let GenericParam::Lifetime(ref mut lifetime) = *next {
217            Some(lifetime)
218        } else {
219            self.next()
220        }
221    }
222}
223
224pub struct ConstParams<'a>(Iter<'a, GenericParam, Token![,]>);
225
226impl<'a> Iterator for ConstParams<'a> {
227    type Item = &'a ConstParam;
228
229    fn next(&mut self) -> Option<Self::Item> {
230        // FIXME: Remove this when ? on Option is stable
231        let next = match self.0.next() {
232            Some(item) => item,
233            None => return None,
234        };
235        if let GenericParam::Const(ref const_param) = *next {
236            Some(const_param)
237        } else {
238            self.next()
239        }
240    }
241}
242
243pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam, Token![,]>);
244
245impl<'a> Iterator for ConstParamsMut<'a> {
246    type Item = &'a mut ConstParam;
247
248    fn next(&mut self) -> Option<Self::Item> {
249        // FIXME: Remove this when ? on Option is stable
250        let next = match self.0.next() {
251            Some(item) => item,
252            None => return None,
253        };
254        if let GenericParam::Const(ref mut const_param) = *next {
255            Some(const_param)
256        } else {
257            self.next()
258        }
259    }
260}
261
262/// Returned by `Generics::split_for_impl`.
263///
264/// *This type is available if Syn is built with the `"derive"` or `"full"`
265/// feature and the `"printing"` feature.*
266#[cfg(feature = "printing")]
267#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
268#[cfg_attr(feature = "clone-impls", derive(Clone))]
269pub struct ImplGenerics<'a>(&'a Generics);
270
271/// Returned by `Generics::split_for_impl`.
272///
273/// *This type is available if Syn is built with the `"derive"` or `"full"`
274/// feature and the `"printing"` feature.*
275#[cfg(feature = "printing")]
276#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
277#[cfg_attr(feature = "clone-impls", derive(Clone))]
278pub struct TypeGenerics<'a>(&'a Generics);
279
280/// Returned by `TypeGenerics::as_turbofish`.
281///
282/// *This type is available if Syn is built with the `"derive"` or `"full"`
283/// feature and the `"printing"` feature.*
284#[cfg(feature = "printing")]
285#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
286#[cfg_attr(feature = "clone-impls", derive(Clone))]
287pub struct Turbofish<'a>(&'a Generics);
288
289#[cfg(feature = "printing")]
290impl Generics {
291    /// Split a type's generics into the pieces required for impl'ing a trait
292    /// for that type.
293    ///
294    /// ```
295    /// # extern crate syn;
296    /// # #[macro_use]
297    /// # extern crate quote;
298    /// # fn main() {
299    /// # let generics: syn::Generics = Default::default();
300    /// # let name = syn::Ident::from("MyType");
301    /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
302    /// quote! {
303    ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
304    ///         // ...
305    ///     }
306    /// }
307    /// # ;
308    /// # }
309    /// ```
310    ///
311    /// *This method is available if Syn is built with the `"derive"` or
312    /// `"full"` feature and the `"printing"` feature.*
313    pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
314        (
315            ImplGenerics(self),
316            TypeGenerics(self),
317            self.where_clause.as_ref(),
318        )
319    }
320}
321
322#[cfg(feature = "printing")]
323impl<'a> TypeGenerics<'a> {
324    /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
325    ///
326    /// *This method is available if Syn is built with the `"derive"` or
327    /// `"full"` feature and the `"printing"` feature.*
328    pub fn as_turbofish(&self) -> Turbofish {
329        Turbofish(self.0)
330    }
331}
332
333ast_struct! {
334    /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
335    ///
336    /// *This type is available if Syn is built with the `"derive"` or `"full"`
337    /// feature.*
338    #[derive(Default)]
339    pub struct BoundLifetimes {
340        pub for_token: Token![for],
341        pub lt_token: Token![<],
342        pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
343        pub gt_token: Token![>],
344    }
345}
346
347impl LifetimeDef {
348    pub fn new(lifetime: Lifetime) -> Self {
349        LifetimeDef {
350            attrs: Vec::new(),
351            lifetime: lifetime,
352            colon_token: None,
353            bounds: Punctuated::new(),
354        }
355    }
356}
357
358impl From<Ident> for TypeParam {
359    fn from(ident: Ident) -> Self {
360        TypeParam {
361            attrs: vec![],
362            ident: ident,
363            colon_token: None,
364            bounds: Punctuated::new(),
365            eq_token: None,
366            default: None,
367        }
368    }
369}
370
371ast_enum_of_structs! {
372    /// A trait or lifetime used as a bound on a type parameter.
373    ///
374    /// *This type is available if Syn is built with the `"derive"` or `"full"`
375    /// feature.*
376    pub enum TypeParamBound {
377        pub Trait(TraitBound),
378        pub Lifetime(Lifetime),
379    }
380}
381
382ast_struct! {
383    /// A trait used as a bound on a type parameter.
384    ///
385    /// *This type is available if Syn is built with the `"derive"` or `"full"`
386    /// feature.*
387    pub struct TraitBound {
388        pub modifier: TraitBoundModifier,
389        /// The `for<'a>` in `for<'a> Foo<&'a T>`
390        pub lifetimes: Option<BoundLifetimes>,
391        /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
392        pub path: Path,
393    }
394}
395
396ast_enum! {
397    /// A modifier on a trait bound, currently only used for the `?` in
398    /// `?Sized`.
399    ///
400    /// *This type is available if Syn is built with the `"derive"` or `"full"`
401    /// feature.*
402    #[cfg_attr(feature = "clone-impls", derive(Copy))]
403    pub enum TraitBoundModifier {
404        None,
405        Maybe(Token![?]),
406    }
407}
408
409ast_struct! {
410    /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
411    /// 'static`.
412    ///
413    /// *This type is available if Syn is built with the `"derive"` or `"full"`
414    /// feature.*
415    pub struct WhereClause {
416        pub where_token: Token![where],
417        pub predicates: Punctuated<WherePredicate, Token![,]>,
418    }
419}
420
421ast_enum_of_structs! {
422    /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
423    ///
424    /// *This type is available if Syn is built with the `"derive"` or `"full"`
425    /// feature.*
426    ///
427    /// # Syntax tree enum
428    ///
429    /// This type is a [syntax tree enum].
430    ///
431    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
432    pub enum WherePredicate {
433        /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
434        ///
435        /// *This type is available if Syn is built with the `"derive"` or
436        /// `"full"` feature.*
437        pub Type(PredicateType {
438            /// Any lifetimes from a `for` binding
439            pub lifetimes: Option<BoundLifetimes>,
440            /// The type being bounded
441            pub bounded_ty: Type,
442            pub colon_token: Token![:],
443            /// Trait and lifetime bounds (`Clone+Send+'static`)
444            pub bounds: Punctuated<TypeParamBound, Token![+]>,
445        }),
446
447        /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
448        ///
449        /// *This type is available if Syn is built with the `"derive"` or
450        /// `"full"` feature.*
451        pub Lifetime(PredicateLifetime {
452            pub lifetime: Lifetime,
453            pub colon_token: Option<Token![:]>,
454            pub bounds: Punctuated<Lifetime, Token![+]>,
455        }),
456
457        /// An equality predicate in a `where` clause (unsupported).
458        ///
459        /// *This type is available if Syn is built with the `"derive"` or
460        /// `"full"` feature.*
461        pub Eq(PredicateEq {
462            pub lhs_ty: Type,
463            pub eq_token: Token![=],
464            pub rhs_ty: Type,
465        }),
466    }
467}
468
469#[cfg(feature = "parsing")]
470pub mod parsing {
471    use super::*;
472
473    use synom::Synom;
474    use punctuated::Pair;
475
476    impl Synom for Generics {
477        named!(parse -> Self, map!(
478            alt!(
479                do_parse!(
480                    lt: punct!(<) >>
481                    lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
482                    ty_params: cond!(
483                        lifetimes.empty_or_trailing(),
484                        Punctuated::<TypeParam, Token![,]>::parse_terminated
485                    ) >>
486                    gt: punct!(>) >>
487                    (lifetimes, ty_params, Some(lt), Some(gt))
488                )
489                |
490                epsilon!() => { |_| (Punctuated::new(), None, None, None) }
491            ),
492            |(lifetimes, ty_params, lt, gt)| Generics {
493                lt_token: lt,
494                params: lifetimes.into_pairs()
495                    .map(Pair::into_tuple)
496                    .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
497                    .chain(ty_params.unwrap_or_default()
498                        .into_pairs()
499                        .map(Pair::into_tuple)
500                        .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
501                    .collect(),
502                gt_token: gt,
503                where_clause: None,
504            }
505        ));
506
507        fn description() -> Option<&'static str> {
508            Some("generic parameters in declaration")
509        }
510    }
511
512    impl Synom for GenericParam {
513        named!(parse -> Self, alt!(
514            syn!(TypeParam) => { GenericParam::Type }
515            |
516            syn!(LifetimeDef) => { GenericParam::Lifetime }
517            |
518            syn!(ConstParam) => { GenericParam::Const }
519        ));
520
521        fn description() -> Option<&'static str> {
522            Some("generic parameter")
523        }
524    }
525
526    impl Synom for LifetimeDef {
527        named!(parse -> Self, do_parse!(
528            attrs: many0!(Attribute::parse_outer) >>
529            life: syn!(Lifetime) >>
530            colon: option!(punct!(:)) >>
531            bounds: cond!(
532                colon.is_some(),
533                Punctuated::parse_separated_nonempty
534            ) >>
535            (LifetimeDef {
536                attrs: attrs,
537                lifetime: life,
538                bounds: bounds.unwrap_or_default(),
539                colon_token: colon,
540            })
541        ));
542
543        fn description() -> Option<&'static str> {
544            Some("lifetime definition")
545        }
546    }
547
548    impl Synom for BoundLifetimes {
549        named!(parse -> Self, do_parse!(
550            for_: keyword!(for) >>
551            lt: punct!(<) >>
552            lifetimes: call!(Punctuated::parse_terminated) >>
553            gt: punct!(>) >>
554            (BoundLifetimes {
555                for_token: for_,
556                lt_token: lt,
557                gt_token: gt,
558                lifetimes: lifetimes,
559            })
560        ));
561
562        fn description() -> Option<&'static str> {
563            Some("bound lifetimes")
564        }
565    }
566
567    impl Synom for TypeParam {
568        named!(parse -> Self, do_parse!(
569            attrs: many0!(Attribute::parse_outer) >>
570            id: syn!(Ident) >>
571            colon: option!(punct!(:)) >>
572            bounds: cond!(
573                colon.is_some(),
574                Punctuated::parse_separated_nonempty
575            ) >>
576            default: option!(do_parse!(
577                eq: punct!(=) >>
578                ty: syn!(Type) >>
579                (eq, ty)
580            )) >>
581            (TypeParam {
582                attrs: attrs,
583                ident: id,
584                bounds: bounds.unwrap_or_default(),
585                colon_token: colon,
586                eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
587                default: default.map(|d| d.1),
588            })
589        ));
590
591        fn description() -> Option<&'static str> {
592            Some("type parameter")
593        }
594    }
595
596    impl Synom for TypeParamBound {
597        named!(parse -> Self, alt!(
598            syn!(Lifetime) => { TypeParamBound::Lifetime }
599            |
600            syn!(TraitBound) => { TypeParamBound::Trait }
601            |
602            parens!(syn!(TraitBound)) => { |bound| TypeParamBound::Trait(bound.1) }
603        ));
604
605        fn description() -> Option<&'static str> {
606            Some("type parameter bound")
607        }
608    }
609
610    impl Synom for TraitBound {
611        named!(parse -> Self, do_parse!(
612            modifier: syn!(TraitBoundModifier) >>
613            lifetimes: option!(syn!(BoundLifetimes)) >>
614            mut path: syn!(Path) >>
615            parenthesized: option!(cond_reduce!(
616                path.segments.last().unwrap().value().arguments.is_empty(),
617                syn!(ParenthesizedGenericArguments)
618            )) >>
619            ({
620                if let Some(parenthesized) = parenthesized {
621                    let parenthesized = PathArguments::Parenthesized(parenthesized);
622                    path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
623                }
624                TraitBound {
625                    modifier: modifier,
626                    lifetimes: lifetimes,
627                    path: path,
628                }
629            })
630        ));
631
632        fn description() -> Option<&'static str> {
633            Some("trait bound")
634        }
635    }
636
637    impl Synom for TraitBoundModifier {
638        named!(parse -> Self, alt!(
639            punct!(?) => { TraitBoundModifier::Maybe }
640            |
641            epsilon!() => { |_| TraitBoundModifier::None }
642        ));
643
644        fn description() -> Option<&'static str> {
645            Some("trait bound modifier")
646        }
647    }
648
649    impl Synom for ConstParam {
650        named!(parse -> Self, do_parse!(
651            attrs: many0!(Attribute::parse_outer) >>
652            const_: keyword!(const) >>
653            ident: syn!(Ident) >>
654            colon: punct!(:) >>
655            ty: syn!(Type) >>
656            eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
657            ({
658                let (eq_token, default) = match eq_def {
659                    Some((eq_token, default)) => (Some(eq_token), Some(default)),
660                    None => (None, None),
661                };
662                ConstParam {
663                    attrs: attrs,
664                    const_token: const_,
665                    ident: ident,
666                    colon_token: colon,
667                    ty: ty,
668                    eq_token: eq_token,
669                    default: default,
670                }
671            })
672        ));
673
674        fn description() -> Option<&'static str> {
675            Some("generic `const` parameter")
676        }
677    }
678
679    impl Synom for WhereClause {
680        named!(parse -> Self, do_parse!(
681            where_: keyword!(where) >>
682            predicates: call!(Punctuated::parse_terminated) >>
683            (WhereClause {
684                predicates: predicates,
685                where_token: where_,
686            })
687        ));
688
689        fn description() -> Option<&'static str> {
690            Some("where clause")
691        }
692    }
693
694    impl Synom for WherePredicate {
695        named!(parse -> Self, alt!(
696            do_parse!(
697                ident: syn!(Lifetime) >>
698                colon: option!(punct!(:)) >>
699                bounds: cond!(
700                    colon.is_some(),
701                    Punctuated::parse_separated
702                ) >>
703                (WherePredicate::Lifetime(PredicateLifetime {
704                    lifetime: ident,
705                    bounds: bounds.unwrap_or_default(),
706                    colon_token: colon,
707                }))
708            )
709            |
710            do_parse!(
711                lifetimes: option!(syn!(BoundLifetimes)) >>
712                bounded_ty: syn!(Type) >>
713                colon: punct!(:) >>
714                bounds: call!(Punctuated::parse_separated_nonempty) >>
715                (WherePredicate::Type(PredicateType {
716                    lifetimes: lifetimes,
717                    bounded_ty: bounded_ty,
718                    bounds: bounds,
719                    colon_token: colon,
720                }))
721            )
722        ));
723
724        fn description() -> Option<&'static str> {
725            Some("predicate in where clause")
726        }
727    }
728}
729
730#[cfg(feature = "printing")]
731mod printing {
732    use super::*;
733    use attr::FilterAttrs;
734    use quote::{ToTokens, Tokens};
735
736    impl ToTokens for Generics {
737        fn to_tokens(&self, tokens: &mut Tokens) {
738            if self.params.is_empty() {
739                return;
740            }
741
742            TokensOrDefault(&self.lt_token).to_tokens(tokens);
743
744            // Print lifetimes before types and consts, regardless of their
745            // order in self.params.
746            //
747            // TODO: ordering rules for const parameters vs type parameters have
748            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
749            let mut trailing_or_empty = true;
750            for param in self.params.pairs() {
751                if let GenericParam::Lifetime(_) = **param.value() {
752                    param.to_tokens(tokens);
753                    trailing_or_empty = param.punct().is_some();
754                }
755            }
756            for param in self.params.pairs() {
757                match **param.value() {
758                    GenericParam::Type(_) | GenericParam::Const(_) => {
759                        if !trailing_or_empty {
760                            <Token![,]>::default().to_tokens(tokens);
761                            trailing_or_empty = true;
762                        }
763                        param.to_tokens(tokens);
764                    }
765                    GenericParam::Lifetime(_) => {}
766                }
767            }
768
769            TokensOrDefault(&self.gt_token).to_tokens(tokens);
770        }
771    }
772
773    impl<'a> ToTokens for ImplGenerics<'a> {
774        fn to_tokens(&self, tokens: &mut Tokens) {
775            if self.0.params.is_empty() {
776                return;
777            }
778
779            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
780
781            // Print lifetimes before types and consts, regardless of their
782            // order in self.params.
783            //
784            // TODO: ordering rules for const parameters vs type parameters have
785            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
786            let mut trailing_or_empty = true;
787            for param in self.0.params.pairs() {
788                if let GenericParam::Lifetime(_) = **param.value() {
789                    param.to_tokens(tokens);
790                    trailing_or_empty = param.punct().is_some();
791                }
792            }
793            for param in self.0.params.pairs() {
794                if let GenericParam::Lifetime(_) = **param.value() {
795                    continue;
796                }
797                if !trailing_or_empty {
798                    <Token![,]>::default().to_tokens(tokens);
799                    trailing_or_empty = true;
800                }
801                match **param.value() {
802                    GenericParam::Lifetime(_) => unreachable!(),
803                    GenericParam::Type(ref param) => {
804                        // Leave off the type parameter defaults
805                        tokens.append_all(param.attrs.outer());
806                        param.ident.to_tokens(tokens);
807                        if !param.bounds.is_empty() {
808                            TokensOrDefault(&param.colon_token).to_tokens(tokens);
809                            param.bounds.to_tokens(tokens);
810                        }
811                    }
812                    GenericParam::Const(ref param) => {
813                        // Leave off the const parameter defaults
814                        tokens.append_all(param.attrs.outer());
815                        param.const_token.to_tokens(tokens);
816                        param.ident.to_tokens(tokens);
817                        param.colon_token.to_tokens(tokens);
818                        param.ty.to_tokens(tokens);
819                    }
820                }
821                param.punct().to_tokens(tokens);
822            }
823
824            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
825        }
826    }
827
828    impl<'a> ToTokens for TypeGenerics<'a> {
829        fn to_tokens(&self, tokens: &mut Tokens) {
830            if self.0.params.is_empty() {
831                return;
832            }
833
834            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
835
836            // Print lifetimes before types and consts, regardless of their
837            // order in self.params.
838            //
839            // TODO: ordering rules for const parameters vs type parameters have
840            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
841            let mut trailing_or_empty = true;
842            for param in self.0.params.pairs() {
843                if let GenericParam::Lifetime(ref def) = **param.value() {
844                    // Leave off the lifetime bounds and attributes
845                    def.lifetime.to_tokens(tokens);
846                    param.punct().to_tokens(tokens);
847                    trailing_or_empty = param.punct().is_some();
848                }
849            }
850            for param in self.0.params.pairs() {
851                if let GenericParam::Lifetime(_) = **param.value() {
852                    continue;
853                }
854                if !trailing_or_empty {
855                    <Token![,]>::default().to_tokens(tokens);
856                    trailing_or_empty = true;
857                }
858                match **param.value() {
859                    GenericParam::Lifetime(_) => unreachable!(),
860                    GenericParam::Type(ref param) => {
861                        // Leave off the type parameter defaults
862                        param.ident.to_tokens(tokens);
863                    }
864                    GenericParam::Const(ref param) => {
865                        // Leave off the const parameter defaults
866                        param.ident.to_tokens(tokens);
867                    }
868                }
869                param.punct().to_tokens(tokens);
870            }
871
872            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
873        }
874    }
875
876    impl<'a> ToTokens for Turbofish<'a> {
877        fn to_tokens(&self, tokens: &mut Tokens) {
878            if !self.0.params.is_empty() {
879                <Token![::]>::default().to_tokens(tokens);
880                TypeGenerics(self.0).to_tokens(tokens);
881            }
882        }
883    }
884
885    impl ToTokens for BoundLifetimes {
886        fn to_tokens(&self, tokens: &mut Tokens) {
887            self.for_token.to_tokens(tokens);
888            self.lt_token.to_tokens(tokens);
889            self.lifetimes.to_tokens(tokens);
890            self.gt_token.to_tokens(tokens);
891        }
892    }
893
894    impl ToTokens for LifetimeDef {
895        fn to_tokens(&self, tokens: &mut Tokens) {
896            tokens.append_all(self.attrs.outer());
897            self.lifetime.to_tokens(tokens);
898            if !self.bounds.is_empty() {
899                TokensOrDefault(&self.colon_token).to_tokens(tokens);
900                self.bounds.to_tokens(tokens);
901            }
902        }
903    }
904
905    impl ToTokens for TypeParam {
906        fn to_tokens(&self, tokens: &mut Tokens) {
907            tokens.append_all(self.attrs.outer());
908            self.ident.to_tokens(tokens);
909            if !self.bounds.is_empty() {
910                TokensOrDefault(&self.colon_token).to_tokens(tokens);
911                self.bounds.to_tokens(tokens);
912            }
913            if self.default.is_some() {
914                TokensOrDefault(&self.eq_token).to_tokens(tokens);
915                self.default.to_tokens(tokens);
916            }
917        }
918    }
919
920    impl ToTokens for TraitBound {
921        fn to_tokens(&self, tokens: &mut Tokens) {
922            self.modifier.to_tokens(tokens);
923            self.lifetimes.to_tokens(tokens);
924            self.path.to_tokens(tokens);
925        }
926    }
927
928    impl ToTokens for TraitBoundModifier {
929        fn to_tokens(&self, tokens: &mut Tokens) {
930            match *self {
931                TraitBoundModifier::None => {}
932                TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
933            }
934        }
935    }
936
937    impl ToTokens for ConstParam {
938        fn to_tokens(&self, tokens: &mut Tokens) {
939            tokens.append_all(self.attrs.outer());
940            self.const_token.to_tokens(tokens);
941            self.ident.to_tokens(tokens);
942            self.colon_token.to_tokens(tokens);
943            self.ty.to_tokens(tokens);
944            if self.default.is_some() {
945                TokensOrDefault(&self.eq_token).to_tokens(tokens);
946                self.default.to_tokens(tokens);
947            }
948        }
949    }
950
951    impl ToTokens for WhereClause {
952        fn to_tokens(&self, tokens: &mut Tokens) {
953            self.where_token.to_tokens(tokens);
954            self.predicates.to_tokens(tokens);
955        }
956    }
957
958    impl ToTokens for PredicateType {
959        fn to_tokens(&self, tokens: &mut Tokens) {
960            self.lifetimes.to_tokens(tokens);
961            self.bounded_ty.to_tokens(tokens);
962            self.colon_token.to_tokens(tokens);
963            self.bounds.to_tokens(tokens);
964        }
965    }
966
967    impl ToTokens for PredicateLifetime {
968        fn to_tokens(&self, tokens: &mut Tokens) {
969            self.lifetime.to_tokens(tokens);
970            if !self.bounds.is_empty() {
971                TokensOrDefault(&self.colon_token).to_tokens(tokens);
972                self.bounds.to_tokens(tokens);
973            }
974        }
975    }
976
977    impl ToTokens for PredicateEq {
978        fn to_tokens(&self, tokens: &mut Tokens) {
979            self.lhs_ty.to_tokens(tokens);
980            self.eq_token.to_tokens(tokens);
981            self.rhs_ty.to_tokens(tokens);
982        }
983    }
984}