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