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