standalone_syn/
ty.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 punctuated::Punctuated;
10use super::*;
11use proc_macro2::TokenStream;
12#[cfg(feature = "extra-traits")]
13use std::hash::{Hash, Hasher};
14#[cfg(feature = "extra-traits")]
15use tt::TokenStreamHelper;
16
17ast_enum_of_structs! {
18    /// The possible types that a Rust value could have.
19    ///
20    /// *This type is available if Syn is built with the `"derive"` or `"full"`
21    /// feature.*
22    ///
23    /// # Syntax tree enum
24    ///
25    /// This type is a [syntax tree enum].
26    ///
27    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
28    pub enum Type {
29        /// A dynamically sized slice type: `[T]`.
30        ///
31        /// *This type is available if Syn is built with the `"derive"` or
32        /// `"full"` feature.*
33        pub Slice(TypeSlice {
34            pub bracket_token: token::Bracket,
35            pub elem: Box<Type>,
36        }),
37
38        /// A fixed size array type: `[T; n]`.
39        ///
40        /// *This type is available if Syn is built with the `"derive"` or
41        /// `"full"` feature.*
42        pub Array(TypeArray {
43            pub bracket_token: token::Bracket,
44            pub elem: Box<Type>,
45            pub semi_token: Token![;],
46            pub len: Expr,
47        }),
48
49        /// A raw pointer type: `*const T` or `*mut T`.
50        ///
51        /// *This type is available if Syn is built with the `"derive"` or
52        /// `"full"` feature.*
53        pub Ptr(TypePtr {
54            pub star_token: Token![*],
55            pub const_token: Option<Token![const]>,
56            pub mutability: Option<Token![mut]>,
57            pub elem: Box<Type>,
58        }),
59
60        /// A reference type: `&'a T` or `&'a mut T`.
61        ///
62        /// *This type is available if Syn is built with the `"derive"` or
63        /// `"full"` feature.*
64        pub Reference(TypeReference {
65            pub and_token: Token![&],
66            pub lifetime: Option<Lifetime>,
67            pub mutability: Option<Token![mut]>,
68            pub elem: Box<Type>,
69        }),
70
71        /// A bare function type: `fn(usize) -> bool`.
72        ///
73        /// *This type is available if Syn is built with the `"derive"` or
74        /// `"full"` feature.*
75        pub BareFn(TypeBareFn {
76            pub unsafety: Option<Token![unsafe]>,
77            pub abi: Option<Abi>,
78            pub fn_token: Token![fn],
79            pub lifetimes: Option<BoundLifetimes>,
80            pub paren_token: token::Paren,
81            pub inputs: Punctuated<BareFnArg, Token![,]>,
82            pub variadic: Option<Token![...]>,
83            pub output: ReturnType,
84        }),
85
86        /// The never type: `!`.
87        ///
88        /// *This type is available if Syn is built with the `"derive"` or
89        /// `"full"` feature.*
90        pub Never(TypeNever {
91            pub bang_token: Token![!],
92        }),
93
94        /// A tuple type: `(A, B, C, String)`.
95        ///
96        /// *This type is available if Syn is built with the `"derive"` or
97        /// `"full"` feature.*
98        pub Tuple(TypeTuple {
99            pub paren_token: token::Paren,
100            pub elems: Punctuated<Type, Token![,]>,
101        }),
102
103        /// A path like `std::slice::Iter`, optionally qualified with a
104        /// self-type as in `<Vec<T> as SomeTrait>::Associated`.
105        ///
106        /// Type arguments are stored in the Path itself.
107        ///
108        /// *This type is available if Syn is built with the `"derive"` or
109        /// `"full"` feature.*
110        pub Path(TypePath {
111            pub qself: Option<QSelf>,
112            pub path: Path,
113        }),
114
115        /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a
116        /// trait or a lifetime.
117        ///
118        /// *This type is available if Syn is built with the `"derive"` or
119        /// `"full"` feature.*
120        pub TraitObject(TypeTraitObject {
121            pub dyn_token: Option<Token![dyn]>,
122            pub bounds: Punctuated<TypeParamBound, Token![+]>,
123        }),
124
125        /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
126        /// a lifetime.
127        ///
128        /// *This type is available if Syn is built with the `"derive"` or
129        /// `"full"` feature.*
130        pub ImplTrait(TypeImplTrait {
131            pub impl_token: Token![impl],
132            pub bounds: Punctuated<TypeParamBound, Token![+]>,
133        }),
134
135        /// A parenthesized type equivalent to the inner type.
136        ///
137        /// *This type is available if Syn is built with the `"derive"` or
138        /// `"full"` feature.*
139        pub Paren(TypeParen {
140            pub paren_token: token::Paren,
141            pub elem: Box<Type>,
142        }),
143
144        /// A type contained within invisible delimiters.
145        ///
146        /// *This type is available if Syn is built with the `"derive"` or
147        /// `"full"` feature.*
148        pub Group(TypeGroup {
149            pub group_token: token::Group,
150            pub elem: Box<Type>,
151        }),
152
153        /// Indication that a type should be inferred by the compiler: `_`.
154        ///
155        /// *This type is available if Syn is built with the `"derive"` or
156        /// `"full"` feature.*
157        pub Infer(TypeInfer {
158            pub underscore_token: Token![_],
159        }),
160
161        /// A macro in the type position.
162        ///
163        /// *This type is available if Syn is built with the `"derive"` or
164        /// `"full"` feature.*
165        pub Macro(TypeMacro {
166            pub mac: Macro,
167        }),
168
169        /// Tokens in type position not interpreted by Syn.
170        ///
171        /// *This type is available if Syn is built with the `"derive"` or
172        /// `"full"` feature.*
173        pub Verbatim(TypeVerbatim #manual_extra_traits {
174            pub tts: TokenStream,
175        }),
176    }
177}
178
179#[cfg(feature = "extra-traits")]
180impl Eq for TypeVerbatim {}
181
182#[cfg(feature = "extra-traits")]
183impl PartialEq for TypeVerbatim {
184    fn eq(&self, other: &Self) -> bool {
185        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
186    }
187}
188
189#[cfg(feature = "extra-traits")]
190impl Hash for TypeVerbatim {
191    fn hash<H>(&self, state: &mut H)
192    where
193        H: Hasher,
194    {
195        TokenStreamHelper(&self.tts).hash(state);
196    }
197}
198
199ast_struct! {
200    /// The binary interface of a function: `extern "C"`.
201    ///
202    /// *This type is available if Syn is built with the `"derive"` or `"full"`
203    /// feature.*
204    pub struct Abi {
205        pub extern_token: Token![extern],
206        pub name: Option<LitStr>,
207    }
208}
209
210ast_struct! {
211    /// An argument in a function type: the `usize` in `fn(usize) -> bool`.
212    ///
213    /// *This type is available if Syn is built with the `"derive"` or `"full"`
214    /// feature.*
215    pub struct BareFnArg {
216        pub name: Option<(BareFnArgName, Token![:])>,
217        pub ty: Type,
218    }
219}
220
221ast_enum! {
222    /// Name of an argument in a function type: the `n` in `fn(n: usize)`.
223    ///
224    /// *This type is available if Syn is built with the `"derive"` or `"full"`
225    /// feature.*
226    pub enum BareFnArgName {
227        /// Argument given a name.
228        Named(Ident),
229        /// Argument not given a name, matched with `_`.
230        Wild(Token![_]),
231    }
232}
233
234ast_enum! {
235    /// Return type of a function signature.
236    ///
237    /// *This type is available if Syn is built with the `"derive"` or `"full"`
238    /// feature.*
239    pub enum ReturnType {
240        /// Return type is not specified.
241        ///
242        /// Functions default to `()` and closures default to type inference.
243        Default,
244        /// A particular type is returned.
245        Type(Token![->], Box<Type>),
246    }
247}
248
249#[cfg(feature = "parsing")]
250pub mod parsing {
251    use super::*;
252    use synom::Synom;
253    use path::parsing::qpath;
254
255    impl Synom for Type {
256        named!(parse -> Self, call!(ambig_ty, true));
257
258        fn description() -> Option<&'static str> {
259            Some("type")
260        }
261    }
262
263    impl Type {
264        /// In some positions, types may not contain the `+` character, to
265        /// disambiguate them. For example in the expression `1 as T`, T may not
266        /// contain a `+` character.
267        ///
268        /// This parser does not allow a `+`, while the default parser does.
269        named!(pub without_plus -> Self, call!(ambig_ty, false));
270    }
271
272    named!(ambig_ty(allow_plus: bool) -> Type, alt!(
273        syn!(TypeGroup) => { Type::Group }
274        |
275        // must be before TypeTuple
276        call!(TypeParen::parse, allow_plus) => { Type::Paren }
277        |
278        // must be before TypePath
279        syn!(TypeMacro) => { Type::Macro }
280        |
281        // must be before TypeTraitObject
282        call!(TypePath::parse, allow_plus) => { Type::Path }
283        |
284        // Don't try parsing more than one trait bound if we aren't allowing it.
285        // must be before TypeTuple
286        call!(TypeTraitObject::parse, allow_plus) => { Type::TraitObject }
287        |
288        syn!(TypeSlice) => { Type::Slice }
289        |
290        syn!(TypeArray) => { Type::Array }
291        |
292        syn!(TypePtr) => { Type::Ptr }
293        |
294        syn!(TypeReference) => { Type::Reference }
295        |
296        syn!(TypeBareFn) => { Type::BareFn }
297        |
298        syn!(TypeNever) => { Type::Never }
299        |
300        syn!(TypeTuple) => { Type::Tuple }
301        |
302        syn!(TypeImplTrait) => { Type::ImplTrait }
303        |
304        syn!(TypeInfer) => { Type::Infer }
305    ));
306
307    impl Synom for TypeSlice {
308        named!(parse -> Self, map!(
309            brackets!(syn!(Type)),
310            |(b, ty)| TypeSlice {
311                elem: Box::new(ty),
312                bracket_token: b,
313            }
314        ));
315
316        fn description() -> Option<&'static str> {
317            Some("slice type")
318        }
319    }
320
321    impl Synom for TypeArray {
322        named!(parse -> Self, map!(
323            brackets!(do_parse!(
324                elem: syn!(Type) >>
325                    semi: punct!(;) >>
326                    len: syn!(Expr) >>
327                    (elem, semi, len)
328            )),
329            |(brackets, (elem, semi, len))| {
330                TypeArray {
331                    elem: Box::new(elem),
332                    len: len,
333                    bracket_token: brackets,
334                    semi_token: semi,
335                }
336            }
337        ));
338
339        fn description() -> Option<&'static str> {
340            Some("array type")
341        }
342    }
343
344    impl Synom for TypePtr {
345        named!(parse -> Self, do_parse!(
346            star: punct!(*) >>
347            mutability: alt!(
348                keyword!(const) => { |c| (None, Some(c)) }
349                |
350                keyword!(mut) => { |m| (Some(m), None) }
351            ) >>
352            target: call!(Type::without_plus) >>
353            (TypePtr {
354                const_token: mutability.1,
355                star_token: star,
356                mutability: mutability.0,
357                elem: Box::new(target),
358            })
359        ));
360
361        fn description() -> Option<&'static str> {
362            Some("raw pointer type")
363        }
364    }
365
366    impl Synom for TypeReference {
367        named!(parse -> Self, do_parse!(
368            amp: punct!(&) >>
369            life: option!(syn!(Lifetime)) >>
370            mutability: option!(keyword!(mut)) >>
371            // & binds tighter than +, so we don't allow + here.
372            target: call!(Type::without_plus) >>
373            (TypeReference {
374                lifetime: life,
375                mutability: mutability,
376                elem: Box::new(target),
377                and_token: amp,
378            })
379        ));
380
381        fn description() -> Option<&'static str> {
382            Some("reference type")
383        }
384    }
385
386    impl Synom for TypeBareFn {
387        named!(parse -> Self, do_parse!(
388            lifetimes: option!(syn!(BoundLifetimes)) >>
389            unsafety: option!(keyword!(unsafe)) >>
390            abi: option!(syn!(Abi)) >>
391            fn_: keyword!(fn) >>
392            parens: parens!(do_parse!(
393                inputs: call!(Punctuated::parse_terminated) >>
394                variadic: option!(cond_reduce!(inputs.empty_or_trailing(), punct!(...))) >>
395                (inputs, variadic)
396            )) >>
397            output: syn!(ReturnType) >>
398            (TypeBareFn {
399                unsafety: unsafety,
400                abi: abi,
401                lifetimes: lifetimes,
402                output: output,
403                variadic: (parens.1).1,
404                fn_token: fn_,
405                paren_token: parens.0,
406                inputs: (parens.1).0,
407            })
408        ));
409
410        fn description() -> Option<&'static str> {
411            Some("`fn` type")
412        }
413    }
414
415    impl Synom for TypeNever {
416        named!(parse -> Self, map!(
417            punct!(!),
418            |b| TypeNever { bang_token: b }
419        ));
420
421        fn description() -> Option<&'static str> {
422            Some("never type: `!`")
423        }
424    }
425
426    impl Synom for TypeInfer {
427        named!(parse -> Self, map!(
428            punct!(_),
429            |u| TypeInfer { underscore_token: u }
430        ));
431
432        fn description() -> Option<&'static str> {
433            Some("inferred type: `_`")
434        }
435    }
436
437    impl Synom for TypeTuple {
438        named!(parse -> Self, do_parse!(
439            data: parens!(Punctuated::parse_terminated) >>
440            (TypeTuple {
441                paren_token: data.0,
442                elems: data.1,
443            })
444        ));
445
446        fn description() -> Option<&'static str> {
447            Some("tuple type")
448        }
449    }
450
451    impl Synom for TypeMacro {
452        named!(parse -> Self, map!(syn!(Macro), |mac| TypeMacro { mac: mac }));
453
454        fn description() -> Option<&'static str> {
455            Some("macro invocation")
456        }
457    }
458
459    impl Synom for TypePath {
460        named!(parse -> Self, call!(Self::parse, false));
461
462        fn description() -> Option<&'static str> {
463            Some("type path")
464        }
465    }
466
467    impl TypePath {
468        named!(parse(allow_plus: bool) -> Self, do_parse!(
469            qpath: qpath >>
470            parenthesized: option!(cond_reduce!(
471                qpath.1.segments.last().unwrap().value().arguments.is_empty(),
472                syn!(ParenthesizedGenericArguments)
473            )) >>
474            cond!(allow_plus, not!(punct!(+))) >>
475            ({
476                let (qself, mut path) = qpath;
477                if let Some(parenthesized) = parenthesized {
478                    let parenthesized = PathArguments::Parenthesized(parenthesized);
479                    path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
480                }
481                TypePath { qself: qself, path: path }
482            })
483        ));
484    }
485
486    impl Synom for ReturnType {
487        named!(parse -> Self, alt!(
488            do_parse!(
489                arrow: punct!(->) >>
490                ty: syn!(Type) >>
491                (ReturnType::Type(arrow, Box::new(ty)))
492            )
493            |
494            epsilon!() => { |_| ReturnType::Default }
495        ));
496
497        fn description() -> Option<&'static str> {
498            Some("return type")
499        }
500    }
501
502    impl Synom for TypeTraitObject {
503        named!(parse -> Self, call!(Self::parse, true));
504
505        fn description() -> Option<&'static str> {
506            Some("trait object type")
507        }
508    }
509
510    fn at_least_one_type(bounds: &Punctuated<TypeParamBound, Token![+]>) -> bool {
511        for bound in bounds {
512            if let TypeParamBound::Trait(_) = *bound {
513                return true;
514            }
515        }
516        false
517    }
518
519    impl TypeTraitObject {
520        named!(pub without_plus -> Self, call!(Self::parse, false));
521
522        // Only allow multiple trait references if allow_plus is true.
523        named!(parse(allow_plus: bool) -> Self, do_parse!(
524            dyn_token: option!(keyword!(dyn)) >>
525            bounds: alt!(
526                cond_reduce!(allow_plus, Punctuated::parse_terminated_nonempty)
527                |
528                syn!(TypeParamBound) => {|x| {
529                    let mut bounds = Punctuated::new();
530                    bounds.push_value(x);
531                    bounds
532                }}
533            ) >>
534            // Just lifetimes like `'a + 'b` is not a TraitObject.
535            cond_reduce!(at_least_one_type(&bounds)) >>
536            (TypeTraitObject {
537                dyn_token: dyn_token,
538                bounds: bounds,
539            })
540        ));
541    }
542
543    impl Synom for TypeImplTrait {
544        named!(parse -> Self, do_parse!(
545            impl_: keyword!(impl) >>
546            // NOTE: rust-lang/rust#34511 includes discussion about whether or
547            // not + should be allowed in ImplTrait directly without ().
548            elem: call!(Punctuated::parse_terminated_nonempty) >>
549            (TypeImplTrait {
550                impl_token: impl_,
551                bounds: elem,
552            })
553        ));
554
555        fn description() -> Option<&'static str> {
556            Some("`impl Trait` type")
557        }
558    }
559
560    impl Synom for TypeGroup {
561        named!(parse -> Self, do_parse!(
562            data: grouped!(syn!(Type)) >>
563            (TypeGroup {
564                group_token: data.0,
565                elem: Box::new(data.1),
566            })
567        ));
568
569        fn description() -> Option<&'static str> {
570            Some("type surrounded by invisible delimiters")
571        }
572    }
573
574    impl Synom for TypeParen {
575        named!(parse -> Self, call!(Self::parse, false));
576
577        fn description() -> Option<&'static str> {
578            Some("parenthesized type")
579        }
580    }
581
582    impl TypeParen {
583        named!(parse(allow_plus: bool) -> Self, do_parse!(
584            data: parens!(syn!(Type)) >>
585            cond!(allow_plus, not!(punct!(+))) >>
586            (TypeParen {
587                paren_token: data.0,
588                elem: Box::new(data.1),
589            })
590        ));
591    }
592
593    impl Synom for BareFnArg {
594        named!(parse -> Self, do_parse!(
595            name: option!(do_parse!(
596                name: syn!(BareFnArgName) >>
597                not!(punct!(::)) >>
598                colon: punct!(:) >>
599                (name, colon)
600            )) >>
601            ty: syn!(Type) >>
602            (BareFnArg {
603                name: name,
604                ty: ty,
605            })
606        ));
607
608        fn description() -> Option<&'static str> {
609            Some("function type argument")
610        }
611    }
612
613    impl Synom for BareFnArgName {
614        named!(parse -> Self, alt!(
615            map!(syn!(Ident), BareFnArgName::Named)
616            |
617            map!(punct!(_), BareFnArgName::Wild)
618        ));
619
620        fn description() -> Option<&'static str> {
621            Some("function argument name")
622        }
623    }
624
625    impl Synom for Abi {
626        named!(parse -> Self, do_parse!(
627            extern_: keyword!(extern) >>
628            name: option!(syn!(LitStr)) >>
629            (Abi {
630                extern_token: extern_,
631                name: name,
632            })
633        ));
634
635        fn description() -> Option<&'static str> {
636            Some("`extern` ABI qualifier")
637        }
638    }
639}
640
641#[cfg(feature = "printing")]
642mod printing {
643    use super::*;
644    use quote::{ToTokens, Tokens};
645
646    impl ToTokens for TypeSlice {
647        fn to_tokens(&self, tokens: &mut Tokens) {
648            self.bracket_token.surround(tokens, |tokens| {
649                self.elem.to_tokens(tokens);
650            });
651        }
652    }
653
654    impl ToTokens for TypeArray {
655        fn to_tokens(&self, tokens: &mut Tokens) {
656            self.bracket_token.surround(tokens, |tokens| {
657                self.elem.to_tokens(tokens);
658                self.semi_token.to_tokens(tokens);
659                self.len.to_tokens(tokens);
660            });
661        }
662    }
663
664    impl ToTokens for TypePtr {
665        fn to_tokens(&self, tokens: &mut Tokens) {
666            self.star_token.to_tokens(tokens);
667            match self.mutability {
668                Some(ref tok) => tok.to_tokens(tokens),
669                None => {
670                    TokensOrDefault(&self.const_token).to_tokens(tokens);
671                }
672            }
673            self.elem.to_tokens(tokens);
674        }
675    }
676
677    impl ToTokens for TypeReference {
678        fn to_tokens(&self, tokens: &mut Tokens) {
679            self.and_token.to_tokens(tokens);
680            self.lifetime.to_tokens(tokens);
681            self.mutability.to_tokens(tokens);
682            self.elem.to_tokens(tokens);
683        }
684    }
685
686    impl ToTokens for TypeBareFn {
687        fn to_tokens(&self, tokens: &mut Tokens) {
688            self.lifetimes.to_tokens(tokens);
689            self.unsafety.to_tokens(tokens);
690            self.abi.to_tokens(tokens);
691            self.fn_token.to_tokens(tokens);
692            self.paren_token.surround(tokens, |tokens| {
693                self.inputs.to_tokens(tokens);
694                if let Some(ref variadic) = self.variadic {
695                    if !self.inputs.empty_or_trailing() {
696                        let span = variadic.0[0];
697                        <Token![,]>::new(span).to_tokens(tokens);
698                    }
699                    variadic.to_tokens(tokens);
700                }
701            });
702            self.output.to_tokens(tokens);
703        }
704    }
705
706    impl ToTokens for TypeNever {
707        fn to_tokens(&self, tokens: &mut Tokens) {
708            self.bang_token.to_tokens(tokens);
709        }
710    }
711
712    impl ToTokens for TypeTuple {
713        fn to_tokens(&self, tokens: &mut Tokens) {
714            self.paren_token.surround(tokens, |tokens| {
715                self.elems.to_tokens(tokens);
716            })
717        }
718    }
719
720    impl ToTokens for TypePath {
721        fn to_tokens(&self, tokens: &mut Tokens) {
722            PathTokens(&self.qself, &self.path).to_tokens(tokens);
723        }
724    }
725
726    impl ToTokens for TypeTraitObject {
727        fn to_tokens(&self, tokens: &mut Tokens) {
728            self.dyn_token.to_tokens(tokens);
729            self.bounds.to_tokens(tokens);
730        }
731    }
732
733    impl ToTokens for TypeImplTrait {
734        fn to_tokens(&self, tokens: &mut Tokens) {
735            self.impl_token.to_tokens(tokens);
736            self.bounds.to_tokens(tokens);
737        }
738    }
739
740    impl ToTokens for TypeGroup {
741        fn to_tokens(&self, tokens: &mut Tokens) {
742            self.group_token.surround(tokens, |tokens| {
743                self.elem.to_tokens(tokens);
744            });
745        }
746    }
747
748    impl ToTokens for TypeParen {
749        fn to_tokens(&self, tokens: &mut Tokens) {
750            self.paren_token.surround(tokens, |tokens| {
751                self.elem.to_tokens(tokens);
752            });
753        }
754    }
755
756    impl ToTokens for TypeInfer {
757        fn to_tokens(&self, tokens: &mut Tokens) {
758            self.underscore_token.to_tokens(tokens);
759        }
760    }
761
762    impl ToTokens for TypeMacro {
763        fn to_tokens(&self, tokens: &mut Tokens) {
764            self.mac.to_tokens(tokens);
765        }
766    }
767
768    impl ToTokens for TypeVerbatim {
769        fn to_tokens(&self, tokens: &mut Tokens) {
770            self.tts.to_tokens(tokens);
771        }
772    }
773
774    impl ToTokens for ReturnType {
775        fn to_tokens(&self, tokens: &mut Tokens) {
776            match *self {
777                ReturnType::Default => {}
778                ReturnType::Type(ref arrow, ref ty) => {
779                    arrow.to_tokens(tokens);
780                    ty.to_tokens(tokens);
781                }
782            }
783        }
784    }
785
786    impl ToTokens for BareFnArg {
787        fn to_tokens(&self, tokens: &mut Tokens) {
788            if let Some((ref name, ref colon)) = self.name {
789                name.to_tokens(tokens);
790                colon.to_tokens(tokens);
791            }
792            self.ty.to_tokens(tokens);
793        }
794    }
795
796    impl ToTokens for BareFnArgName {
797        fn to_tokens(&self, tokens: &mut Tokens) {
798            match *self {
799                BareFnArgName::Named(ref t) => t.to_tokens(tokens),
800                BareFnArgName::Wild(ref t) => t.to_tokens(tokens),
801            }
802        }
803    }
804
805    impl ToTokens for Abi {
806        fn to_tokens(&self, tokens: &mut Tokens) {
807            self.extern_token.to_tokens(tokens);
808            self.name.to_tokens(tokens);
809        }
810    }
811}