]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/token.rs
parser: allow ABIs from literal macro fragments
[rust.git] / src / libsyntax / parse / token.rs
1 pub use BinOpToken::*;
2 pub use Nonterminal::*;
3 pub use DelimToken::*;
4 pub use LitKind::*;
5 pub use TokenKind::*;
6
7 use crate::ast;
8 use crate::ptr::P;
9 use crate::symbol::kw;
10 use crate::tokenstream::TokenTree;
11
12 use syntax_pos::symbol::Symbol;
13 use syntax_pos::{self, Span, DUMMY_SP};
14
15 use std::fmt;
16 use std::mem;
17 #[cfg(target_arch = "x86_64")]
18 use rustc_data_structures::static_assert_size;
19 use rustc_data_structures::sync::Lrc;
20
21 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
22 pub enum BinOpToken {
23     Plus,
24     Minus,
25     Star,
26     Slash,
27     Percent,
28     Caret,
29     And,
30     Or,
31     Shl,
32     Shr,
33 }
34
35 /// A delimiter token.
36 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
37 pub enum DelimToken {
38     /// A round parenthesis (i.e., `(` or `)`).
39     Paren,
40     /// A square bracket (i.e., `[` or `]`).
41     Bracket,
42     /// A curly brace (i.e., `{` or `}`).
43     Brace,
44     /// An empty delimiter.
45     NoDelim,
46 }
47
48 impl DelimToken {
49     pub fn len(self) -> usize {
50         if self == NoDelim { 0 } else { 1 }
51     }
52
53     pub fn is_empty(self) -> bool {
54         self == NoDelim
55     }
56 }
57
58 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
59 pub enum LitKind {
60     Bool, // AST only, must never appear in a `Token`
61     Byte,
62     Char,
63     Integer,
64     Float,
65     Str,
66     StrRaw(u16), // raw string delimited by `n` hash symbols
67     ByteStr,
68     ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols
69     Err,
70 }
71
72 /// A literal token.
73 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
74 pub struct Lit {
75     pub kind: LitKind,
76     pub symbol: Symbol,
77     pub suffix: Option<Symbol>,
78 }
79
80 impl fmt::Display for Lit {
81     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82         let Lit { kind, symbol, suffix } = *self;
83         match kind {
84             Byte          => write!(f, "b'{}'", symbol)?,
85             Char          => write!(f, "'{}'", symbol)?,
86             Str           => write!(f, "\"{}\"", symbol)?,
87             StrRaw(n)     => write!(f, "r{delim}\"{string}\"{delim}",
88                                      delim="#".repeat(n as usize),
89                                      string=symbol)?,
90             ByteStr       => write!(f, "b\"{}\"", symbol)?,
91             ByteStrRaw(n) => write!(f, "br{delim}\"{string}\"{delim}",
92                                      delim="#".repeat(n as usize),
93                                      string=symbol)?,
94             Integer       |
95             Float         |
96             Bool          |
97             Err           => write!(f, "{}", symbol)?,
98         }
99
100         if let Some(suffix) = suffix {
101             write!(f, "{}", suffix)?;
102         }
103
104         Ok(())
105     }
106 }
107
108 impl LitKind {
109     /// An English article for the literal token kind.
110     crate fn article(self) -> &'static str {
111         match self {
112             Integer | Err => "an",
113             _ => "a",
114         }
115     }
116
117     crate fn descr(self) -> &'static str {
118         match self {
119             Bool => panic!("literal token contains `Lit::Bool`"),
120             Byte => "byte",
121             Char => "char",
122             Integer => "integer",
123             Float => "float",
124             Str | StrRaw(..) => "string",
125             ByteStr | ByteStrRaw(..) => "byte string",
126             Err => "error",
127         }
128     }
129
130     crate fn may_have_suffix(self) -> bool {
131         match self {
132             Integer | Float | Err => true,
133             _ => false,
134         }
135     }
136 }
137
138 impl Lit {
139     pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
140         Lit { kind, symbol, suffix }
141     }
142 }
143
144 pub(crate) fn ident_can_begin_expr(name: ast::Name, span: Span, is_raw: bool) -> bool {
145     let ident_token = Token::new(Ident(name, is_raw), span);
146     token_can_begin_expr(&ident_token)
147 }
148
149 pub(crate) fn token_can_begin_expr(ident_token: &Token) -> bool {
150     !ident_token.is_reserved_ident() ||
151     ident_token.is_path_segment_keyword() ||
152     match ident_token.kind {
153         TokenKind::Ident(ident, _) => [
154             kw::Async,
155             kw::Do,
156             kw::Box,
157             kw::Break,
158             kw::Continue,
159             kw::False,
160             kw::For,
161             kw::If,
162             kw::Let,
163             kw::Loop,
164             kw::Match,
165             kw::Move,
166             kw::Return,
167             kw::True,
168             kw::Unsafe,
169             kw::While,
170             kw::Yield,
171             kw::Static,
172         ].contains(&ident),
173         _=> false,
174     }
175 }
176
177 fn ident_can_begin_type(name: ast::Name, span: Span, is_raw: bool) -> bool {
178     let ident_token = Token::new(Ident(name, is_raw), span);
179
180     !ident_token.is_reserved_ident() ||
181     ident_token.is_path_segment_keyword() ||
182     [
183         kw::Underscore,
184         kw::For,
185         kw::Impl,
186         kw::Fn,
187         kw::Unsafe,
188         kw::Extern,
189         kw::Typeof,
190         kw::Dyn,
191     ].contains(&name)
192 }
193
194 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
195 pub enum TokenKind {
196     /* Expression-operator symbols. */
197     Eq,
198     Lt,
199     Le,
200     EqEq,
201     Ne,
202     Ge,
203     Gt,
204     AndAnd,
205     OrOr,
206     Not,
207     Tilde,
208     BinOp(BinOpToken),
209     BinOpEq(BinOpToken),
210
211     /* Structural symbols */
212     At,
213     Dot,
214     DotDot,
215     DotDotDot,
216     DotDotEq,
217     Comma,
218     Semi,
219     Colon,
220     ModSep,
221     RArrow,
222     LArrow,
223     FatArrow,
224     Pound,
225     Dollar,
226     Question,
227     /// Used by proc macros for representing lifetimes, not generated by lexer right now.
228     SingleQuote,
229     /// An opening delimiter (e.g., `{`).
230     OpenDelim(DelimToken),
231     /// A closing delimiter (e.g., `}`).
232     CloseDelim(DelimToken),
233
234     /* Literals */
235     Literal(Lit),
236
237     /* Name components */
238     Ident(ast::Name, /* is_raw */ bool),
239     Lifetime(ast::Name),
240
241     Interpolated(Lrc<Nonterminal>),
242
243     // Can be expanded into several tokens.
244     /// A doc comment.
245     DocComment(ast::Name),
246
247     // Junk. These carry no data because we don't really care about the data
248     // they *would* carry, and don't really want to allocate a new ident for
249     // them. Instead, users could extract that from the associated span.
250
251     /// Whitespace.
252     Whitespace,
253     /// A comment.
254     Comment,
255     Shebang(ast::Name),
256     /// A completely invalid token which should be skipped.
257     Unknown(ast::Name),
258
259     Eof,
260 }
261
262 // `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
263 #[cfg(target_arch = "x86_64")]
264 static_assert_size!(TokenKind, 16);
265
266 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
267 pub struct Token {
268     pub kind: TokenKind,
269     pub span: Span,
270 }
271
272 impl TokenKind {
273     pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
274         Literal(Lit::new(kind, symbol, suffix))
275     }
276
277     /// Returns tokens that are likely to be typed accidentally instead of the current token.
278     /// Enables better error recovery when the wrong token is found.
279     crate fn similar_tokens(&self) -> Option<Vec<TokenKind>> {
280         match *self {
281             Comma => Some(vec![Dot, Lt, Semi]),
282             Semi => Some(vec![Colon, Comma]),
283             _ => None
284         }
285     }
286 }
287
288 impl Token {
289     pub fn new(kind: TokenKind, span: Span) -> Self {
290         Token { kind, span }
291     }
292
293     /// Some token that will be thrown away later.
294     crate fn dummy() -> Self {
295         Token::new(TokenKind::Whitespace, DUMMY_SP)
296     }
297
298     /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
299     pub fn from_ast_ident(ident: ast::Ident) -> Self {
300         Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
301     }
302
303     /// Return this token by value and leave a dummy token in its place.
304     pub fn take(&mut self) -> Self {
305         mem::replace(self, Token::dummy())
306     }
307
308     crate fn is_op(&self) -> bool {
309         match self.kind {
310             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) |
311             Ident(..) | Lifetime(..) | Interpolated(..) |
312             Whitespace | Comment | Shebang(..) | Eof => false,
313             _ => true,
314         }
315     }
316
317     crate fn is_like_plus(&self) -> bool {
318         match self.kind {
319             BinOp(Plus) | BinOpEq(Plus) => true,
320             _ => false,
321         }
322     }
323
324     /// Returns `true` if the token can appear at the start of an expression.
325     pub fn can_begin_expr(&self) -> bool {
326         match self.kind {
327             Ident(name, is_raw)              =>
328                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
329             OpenDelim(..)                     | // tuple, array or block
330             Literal(..)                       | // literal
331             Not                               | // operator not
332             BinOp(Minus)                      | // unary minus
333             BinOp(Star)                       | // dereference
334             BinOp(Or) | OrOr                  | // closure
335             BinOp(And)                        | // reference
336             AndAnd                            | // double reference
337             // DotDotDot is no longer supported, but we need some way to display the error
338             DotDot | DotDotDot | DotDotEq     | // range notation
339             Lt | BinOp(Shl)                   | // associated path
340             ModSep                            | // global path
341             Lifetime(..)                      | // labeled loop
342             Pound                             => true, // expression attributes
343             Interpolated(ref nt) => match **nt {
344                 NtLiteral(..) |
345                 NtIdent(..)   |
346                 NtExpr(..)    |
347                 NtBlock(..)   |
348                 NtPath(..)    |
349                 NtLifetime(..) => true,
350                 _ => false,
351             },
352             _ => false,
353         }
354     }
355
356     /// Returns `true` if the token can appear at the start of a type.
357     pub fn can_begin_type(&self) -> bool {
358         match self.kind {
359             Ident(name, is_raw)        =>
360                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
361             OpenDelim(Paren)            | // tuple
362             OpenDelim(Bracket)          | // array
363             Not                         | // never
364             BinOp(Star)                 | // raw pointer
365             BinOp(And)                  | // reference
366             AndAnd                      | // double reference
367             Question                    | // maybe bound in trait object
368             Lifetime(..)                | // lifetime bound in trait object
369             Lt | BinOp(Shl)             | // associated path
370             ModSep                      => true, // global path
371             Interpolated(ref nt) => match **nt {
372                 NtIdent(..) | NtTy(..) | NtPath(..) | NtLifetime(..) => true,
373                 _ => false,
374             },
375             _ => false,
376         }
377     }
378
379     /// Returns `true` if the token can appear at the start of a const param.
380     crate fn can_begin_const_arg(&self) -> bool {
381         match self.kind {
382             OpenDelim(Brace) => true,
383             Interpolated(ref nt) => match **nt {
384                 NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
385                 _ => false,
386             }
387             _ => self.can_begin_literal_or_bool(),
388         }
389     }
390
391     /// Returns `true` if the token can appear at the start of a generic bound.
392     crate fn can_begin_bound(&self) -> bool {
393         self.is_path_start() || self.is_lifetime() || self.is_keyword(kw::For) ||
394         self == &Question || self == &OpenDelim(Paren)
395     }
396
397     /// Returns `true` if the token is any literal
398     pub fn is_lit(&self) -> bool {
399         match self.kind {
400             Literal(..) => true,
401             _           => false,
402         }
403     }
404
405     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
406     /// for example a '-42', or one of the boolean idents).
407     pub fn can_begin_literal_or_bool(&self) -> bool {
408         match self.kind {
409             Literal(..) | BinOp(Minus) => true,
410             Ident(name, false) if name.is_bool_lit() => true,
411             Interpolated(ref nt) => match **nt {
412                 NtLiteral(..) => true,
413                 _             => false,
414             },
415             _            => false,
416         }
417     }
418
419     /// Returns an identifier if this token is an identifier.
420     pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
421         match self.kind {
422             Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)),
423             Interpolated(ref nt) => match **nt {
424                 NtIdent(ident, is_raw) => Some((ident, is_raw)),
425                 _ => None,
426             },
427             _ => None,
428         }
429     }
430
431     /// Returns a lifetime identifier if this token is a lifetime.
432     pub fn lifetime(&self) -> Option<ast::Ident> {
433         match self.kind {
434             Lifetime(name) => Some(ast::Ident::new(name, self.span)),
435             Interpolated(ref nt) => match **nt {
436                 NtLifetime(ident) => Some(ident),
437                 _ => None,
438             },
439             _ => None,
440         }
441     }
442
443     /// Returns `true` if the token is an identifier.
444     pub fn is_ident(&self) -> bool {
445         self.ident().is_some()
446     }
447
448     /// Returns `true` if the token is a lifetime.
449     crate fn is_lifetime(&self) -> bool {
450         self.lifetime().is_some()
451     }
452
453     /// Returns `true` if the token is a identifier whose name is the given
454     /// string slice.
455     crate fn is_ident_named(&self, name: Symbol) -> bool {
456         self.ident().map_or(false, |(ident, _)| ident.name == name)
457     }
458
459     /// Returns `true` if the token is an interpolated path.
460     fn is_path(&self) -> bool {
461         if let Interpolated(ref nt) = self.kind {
462             if let NtPath(..) = **nt {
463                 return true;
464             }
465         }
466         false
467     }
468
469     /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
470     /// That is, is this a pre-parsed expression dropped into the token stream
471     /// (which happens while parsing the result of macro expansion)?
472     crate fn is_whole_expr(&self) -> bool {
473         if let Interpolated(ref nt) = self.kind {
474             if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt {
475                 return true;
476             }
477         }
478
479         false
480     }
481
482     /// Returns `true` if the token is either the `mut` or `const` keyword.
483     crate fn is_mutability(&self) -> bool {
484         self.is_keyword(kw::Mut) ||
485         self.is_keyword(kw::Const)
486     }
487
488     crate fn is_qpath_start(&self) -> bool {
489         self == &Lt || self == &BinOp(Shl)
490     }
491
492     crate fn is_path_start(&self) -> bool {
493         self == &ModSep || self.is_qpath_start() || self.is_path() ||
494         self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident()
495     }
496
497     /// Returns `true` if the token is a given keyword, `kw`.
498     pub fn is_keyword(&self, kw: Symbol) -> bool {
499         self.is_non_raw_ident_where(|id| id.name == kw)
500     }
501
502     crate fn is_path_segment_keyword(&self) -> bool {
503         self.is_non_raw_ident_where(ast::Ident::is_path_segment_keyword)
504     }
505
506     // Returns true for reserved identifiers used internally for elided lifetimes,
507     // unnamed method parameters, crate root module, error recovery etc.
508     crate fn is_special_ident(&self) -> bool {
509         self.is_non_raw_ident_where(ast::Ident::is_special)
510     }
511
512     /// Returns `true` if the token is a keyword used in the language.
513     crate fn is_used_keyword(&self) -> bool {
514         self.is_non_raw_ident_where(ast::Ident::is_used_keyword)
515     }
516
517     /// Returns `true` if the token is a keyword reserved for possible future use.
518     crate fn is_unused_keyword(&self) -> bool {
519         self.is_non_raw_ident_where(ast::Ident::is_unused_keyword)
520     }
521
522     /// Returns `true` if the token is either a special identifier or a keyword.
523     pub fn is_reserved_ident(&self) -> bool {
524         self.is_non_raw_ident_where(ast::Ident::is_reserved)
525     }
526
527     /// Returns `true` if the token is the identifier `true` or `false`.
528     crate fn is_bool_lit(&self) -> bool {
529         self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
530     }
531
532     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
533     fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool {
534         match self.ident() {
535             Some((id, false)) => pred(id),
536             _ => false,
537         }
538     }
539
540     crate fn glue(&self, joint: &Token) -> Option<Token> {
541         let kind = match self.kind {
542             Eq => match joint.kind {
543                 Eq => EqEq,
544                 Gt => FatArrow,
545                 _ => return None,
546             },
547             Lt => match joint.kind {
548                 Eq => Le,
549                 Lt => BinOp(Shl),
550                 Le => BinOpEq(Shl),
551                 BinOp(Minus) => LArrow,
552                 _ => return None,
553             },
554             Gt => match joint.kind {
555                 Eq => Ge,
556                 Gt => BinOp(Shr),
557                 Ge => BinOpEq(Shr),
558                 _ => return None,
559             },
560             Not => match joint.kind {
561                 Eq => Ne,
562                 _ => return None,
563             },
564             BinOp(op) => match joint.kind {
565                 Eq => BinOpEq(op),
566                 BinOp(And) if op == And => AndAnd,
567                 BinOp(Or) if op == Or => OrOr,
568                 Gt if op == Minus => RArrow,
569                 _ => return None,
570             },
571             Dot => match joint.kind {
572                 Dot => DotDot,
573                 DotDot => DotDotDot,
574                 _ => return None,
575             },
576             DotDot => match joint.kind {
577                 Dot => DotDotDot,
578                 Eq => DotDotEq,
579                 _ => return None,
580             },
581             Colon => match joint.kind {
582                 Colon => ModSep,
583                 _ => return None,
584             },
585             SingleQuote => match joint.kind {
586                 Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
587                 _ => return None,
588             },
589
590             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot |
591             DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
592             Question | OpenDelim(..) | CloseDelim(..) |
593             Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
594             Whitespace | Comment | Shebang(..) | Unknown(..) | Eof => return None,
595         };
596
597         Some(Token::new(kind, self.span.to(joint.span)))
598     }
599
600     // See comments in `Nonterminal::to_tokenstream` for why we care about
601     // *probably* equal here rather than actual equality
602     crate fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
603         if mem::discriminant(&self.kind) != mem::discriminant(&other.kind) {
604             return false
605         }
606         match (&self.kind, &other.kind) {
607             (&Eq, &Eq) |
608             (&Lt, &Lt) |
609             (&Le, &Le) |
610             (&EqEq, &EqEq) |
611             (&Ne, &Ne) |
612             (&Ge, &Ge) |
613             (&Gt, &Gt) |
614             (&AndAnd, &AndAnd) |
615             (&OrOr, &OrOr) |
616             (&Not, &Not) |
617             (&Tilde, &Tilde) |
618             (&At, &At) |
619             (&Dot, &Dot) |
620             (&DotDot, &DotDot) |
621             (&DotDotDot, &DotDotDot) |
622             (&DotDotEq, &DotDotEq) |
623             (&Comma, &Comma) |
624             (&Semi, &Semi) |
625             (&Colon, &Colon) |
626             (&ModSep, &ModSep) |
627             (&RArrow, &RArrow) |
628             (&LArrow, &LArrow) |
629             (&FatArrow, &FatArrow) |
630             (&Pound, &Pound) |
631             (&Dollar, &Dollar) |
632             (&Question, &Question) |
633             (&Whitespace, &Whitespace) |
634             (&Comment, &Comment) |
635             (&Eof, &Eof) => true,
636
637             (&BinOp(a), &BinOp(b)) |
638             (&BinOpEq(a), &BinOpEq(b)) => a == b,
639
640             (&OpenDelim(a), &OpenDelim(b)) |
641             (&CloseDelim(a), &CloseDelim(b)) => a == b,
642
643             (&DocComment(a), &DocComment(b)) |
644             (&Shebang(a), &Shebang(b)) => a == b,
645
646             (&Literal(a), &Literal(b)) => a == b,
647
648             (&Lifetime(a), &Lifetime(b)) => a == b,
649             (&Ident(a, b), &Ident(c, d)) => b == d && (a == c ||
650                                                        a == kw::DollarCrate ||
651                                                        c == kw::DollarCrate),
652
653             (&Interpolated(_), &Interpolated(_)) => false,
654
655             _ => panic!("forgot to add a token?"),
656         }
657     }
658 }
659
660 impl PartialEq<TokenKind> for Token {
661     fn eq(&self, rhs: &TokenKind) -> bool {
662         self.kind == *rhs
663     }
664 }
665
666 #[derive(Clone, RustcEncodable, RustcDecodable)]
667 /// For interpolation during macro expansion.
668 pub enum Nonterminal {
669     NtItem(P<ast::Item>),
670     NtBlock(P<ast::Block>),
671     NtStmt(ast::Stmt),
672     NtPat(P<ast::Pat>),
673     NtExpr(P<ast::Expr>),
674     NtTy(P<ast::Ty>),
675     NtIdent(ast::Ident, /* is_raw */ bool),
676     NtLifetime(ast::Ident),
677     NtLiteral(P<ast::Expr>),
678     /// Stuff inside brackets for attributes
679     NtMeta(ast::AttrItem),
680     NtPath(ast::Path),
681     NtVis(ast::Visibility),
682     NtTT(TokenTree),
683     // Used only for passing items to proc macro attributes (they are not
684     // strictly necessary for that, `Annotatable` can be converted into
685     // tokens directly, but doing that naively regresses pretty-printing).
686     NtTraitItem(ast::TraitItem),
687     NtImplItem(ast::ImplItem),
688     NtForeignItem(ast::ForeignItem),
689 }
690
691 impl PartialEq for Nonterminal {
692     fn eq(&self, rhs: &Self) -> bool {
693         match (self, rhs) {
694             (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) =>
695                 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs,
696             (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
697             (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
698             // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
699             // correctly based on data from AST. This will prevent them from matching each other
700             // in macros. The comparison will become possible only when each nonterminal has an
701             // attached token stream from which it was parsed.
702             _ => false,
703         }
704     }
705 }
706
707 impl fmt::Debug for Nonterminal {
708     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
709         match *self {
710             NtItem(..) => f.pad("NtItem(..)"),
711             NtBlock(..) => f.pad("NtBlock(..)"),
712             NtStmt(..) => f.pad("NtStmt(..)"),
713             NtPat(..) => f.pad("NtPat(..)"),
714             NtExpr(..) => f.pad("NtExpr(..)"),
715             NtTy(..) => f.pad("NtTy(..)"),
716             NtIdent(..) => f.pad("NtIdent(..)"),
717             NtLiteral(..) => f.pad("NtLiteral(..)"),
718             NtMeta(..) => f.pad("NtMeta(..)"),
719             NtPath(..) => f.pad("NtPath(..)"),
720             NtTT(..) => f.pad("NtTT(..)"),
721             NtImplItem(..) => f.pad("NtImplItem(..)"),
722             NtTraitItem(..) => f.pad("NtTraitItem(..)"),
723             NtForeignItem(..) => f.pad("NtForeignItem(..)"),
724             NtVis(..) => f.pad("NtVis(..)"),
725             NtLifetime(..) => f.pad("NtLifetime(..)"),
726         }
727     }
728 }