]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/token.rs
Rollup merge of #67233 - Luro02:cursor_traits, r=sfackler
[rust.git] / src / libsyntax / token.rs
1 pub use BinOpToken::*;
2 pub use DelimToken::*;
3 pub use LitKind::*;
4 pub use Nonterminal::*;
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 rustc_data_structures::stable_hasher::{HashStable, StableHasher};
16 use rustc_data_structures::sync::Lrc;
17 use rustc_macros::HashStable_Generic;
18 use std::fmt;
19 use std::mem;
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!(
90                 f,
91                 "r{delim}\"{string}\"{delim}",
92                 delim = "#".repeat(n as usize),
93                 string = symbol
94             )?,
95             ByteStr => write!(f, "b\"{}\"", symbol)?,
96             ByteStrRaw(n) => write!(
97                 f,
98                 "br{delim}\"{string}\"{delim}",
99                 delim = "#".repeat(n as usize),
100                 string = symbol
101             )?,
102             Integer | Float | Bool | Err => write!(f, "{}", symbol)?,
103         }
104
105         if let Some(suffix) = suffix {
106             write!(f, "{}", suffix)?;
107         }
108
109         Ok(())
110     }
111 }
112
113 impl LitKind {
114     /// An English article for the literal token kind.
115     pub fn article(self) -> &'static str {
116         match self {
117             Integer | Err => "an",
118             _ => "a",
119         }
120     }
121
122     pub fn descr(self) -> &'static str {
123         match self {
124             Bool => panic!("literal token contains `Lit::Bool`"),
125             Byte => "byte",
126             Char => "char",
127             Integer => "integer",
128             Float => "float",
129             Str | StrRaw(..) => "string",
130             ByteStr | ByteStrRaw(..) => "byte string",
131             Err => "error",
132         }
133     }
134
135     crate fn may_have_suffix(self) -> bool {
136         match self {
137             Integer | Float | Err => true,
138             _ => false,
139         }
140     }
141 }
142
143 impl Lit {
144     pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
145         Lit { kind, symbol, suffix }
146     }
147 }
148
149 pub fn ident_can_begin_expr(name: ast::Name, span: Span, is_raw: bool) -> bool {
150     let ident_token = Token::new(Ident(name, is_raw), span);
151     token_can_begin_expr(&ident_token)
152 }
153
154 pub fn token_can_begin_expr(ident_token: &Token) -> bool {
155     !ident_token.is_reserved_ident()
156         || ident_token.is_path_segment_keyword()
157         || match ident_token.kind {
158             TokenKind::Ident(ident, _) => [
159                 kw::Async,
160                 kw::Do,
161                 kw::Box,
162                 kw::Break,
163                 kw::Continue,
164                 kw::False,
165                 kw::For,
166                 kw::If,
167                 kw::Let,
168                 kw::Loop,
169                 kw::Match,
170                 kw::Move,
171                 kw::Return,
172                 kw::True,
173                 kw::Unsafe,
174                 kw::While,
175                 kw::Yield,
176                 kw::Static,
177             ]
178             .contains(&ident),
179             _ => false,
180         }
181 }
182
183 fn ident_can_begin_type(name: ast::Name, span: Span, is_raw: bool) -> bool {
184     let ident_token = Token::new(Ident(name, is_raw), span);
185
186     !ident_token.is_reserved_ident()
187         || ident_token.is_path_segment_keyword()
188         || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
189             .contains(&name)
190 }
191
192 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
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     /// Whitespace.
249     Whitespace,
250     /// A comment.
251     Comment,
252     Shebang(ast::Name),
253     /// A completely invalid token which should be skipped.
254     Unknown(ast::Name),
255
256     Eof,
257 }
258
259 // `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
260 #[cfg(target_arch = "x86_64")]
261 rustc_data_structures::static_assert_size!(TokenKind, 16);
262
263 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
264 pub struct Token {
265     pub kind: TokenKind,
266     pub span: Span,
267 }
268
269 impl TokenKind {
270     pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
271         Literal(Lit::new(kind, symbol, suffix))
272     }
273
274     /// Returns tokens that are likely to be typed accidentally instead of the current token.
275     /// Enables better error recovery when the wrong token is found.
276     pub fn similar_tokens(&self) -> Option<Vec<TokenKind>> {
277         match *self {
278             Comma => Some(vec![Dot, Lt, Semi]),
279             Semi => Some(vec![Colon, Comma]),
280             _ => None,
281         }
282     }
283 }
284
285 impl Token {
286     pub fn new(kind: TokenKind, span: Span) -> Self {
287         Token { kind, span }
288     }
289
290     /// Some token that will be thrown away later.
291     pub fn dummy() -> Self {
292         Token::new(TokenKind::Whitespace, DUMMY_SP)
293     }
294
295     /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
296     pub fn from_ast_ident(ident: ast::Ident) -> Self {
297         Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
298     }
299
300     /// Return this token by value and leave a dummy token in its place.
301     pub fn take(&mut self) -> Self {
302         mem::replace(self, Token::dummy())
303     }
304
305     pub fn is_op(&self) -> bool {
306         match self.kind {
307             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
308             | Lifetime(..) | Interpolated(..) | Whitespace | Comment | Shebang(..) | Eof => false,
309             _ => true,
310         }
311     }
312
313     pub fn is_like_plus(&self) -> bool {
314         match self.kind {
315             BinOp(Plus) | BinOpEq(Plus) => true,
316             _ => false,
317         }
318     }
319
320     /// Returns `true` if the token can appear at the start of an expression.
321     pub fn can_begin_expr(&self) -> bool {
322         match self.kind {
323             Ident(name, is_raw)              =>
324                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
325             OpenDelim(..)                     | // tuple, array or block
326             Literal(..)                       | // literal
327             Not                               | // operator not
328             BinOp(Minus)                      | // unary minus
329             BinOp(Star)                       | // dereference
330             BinOp(Or) | OrOr                  | // closure
331             BinOp(And)                        | // reference
332             AndAnd                            | // double reference
333             // DotDotDot is no longer supported, but we need some way to display the error
334             DotDot | DotDotDot | DotDotEq     | // range notation
335             Lt | BinOp(Shl)                   | // associated path
336             ModSep                            | // global path
337             Lifetime(..)                      | // labeled loop
338             Pound                             => true, // expression attributes
339             Interpolated(ref nt) => match **nt {
340                 NtLiteral(..) |
341                 NtIdent(..)   |
342                 NtExpr(..)    |
343                 NtBlock(..)   |
344                 NtPath(..)    |
345                 NtLifetime(..) => true,
346                 _ => false,
347             },
348             _ => false,
349         }
350     }
351
352     /// Returns `true` if the token can appear at the start of a type.
353     pub fn can_begin_type(&self) -> bool {
354         match self.kind {
355             Ident(name, is_raw)        =>
356                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
357             OpenDelim(Paren)            | // tuple
358             OpenDelim(Bracket)          | // array
359             Not                         | // never
360             BinOp(Star)                 | // raw pointer
361             BinOp(And)                  | // reference
362             AndAnd                      | // double reference
363             Question                    | // maybe bound in trait object
364             Lifetime(..)                | // lifetime bound in trait object
365             Lt | BinOp(Shl)             | // associated path
366             ModSep                      => true, // global path
367             Interpolated(ref nt) => match **nt {
368                 NtIdent(..) | NtTy(..) | NtPath(..) | NtLifetime(..) => true,
369                 _ => false,
370             },
371             _ => false,
372         }
373     }
374
375     /// Returns `true` if the token can appear at the start of a const param.
376     pub fn can_begin_const_arg(&self) -> bool {
377         match self.kind {
378             OpenDelim(Brace) => true,
379             Interpolated(ref nt) => match **nt {
380                 NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
381                 _ => false,
382             },
383             _ => self.can_begin_literal_or_bool(),
384         }
385     }
386
387     /// Returns `true` if the token can appear at the start of a generic bound.
388     pub fn can_begin_bound(&self) -> bool {
389         self.is_path_start()
390             || self.is_lifetime()
391             || self.is_keyword(kw::For)
392             || self == &Question
393             || self == &OpenDelim(Paren)
394     }
395
396     /// Returns `true` if the token is any literal
397     pub fn is_lit(&self) -> bool {
398         match self.kind {
399             Literal(..) => true,
400             _ => false,
401         }
402     }
403
404     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
405     /// for example a '-42', or one of the boolean idents).
406     pub fn can_begin_literal_or_bool(&self) -> bool {
407         match self.kind {
408             Literal(..) | BinOp(Minus) => true,
409             Ident(name, false) if name.is_bool_lit() => true,
410             Interpolated(ref nt) => match **nt {
411                 NtLiteral(..) => true,
412                 _ => false,
413             },
414             _ => false,
415         }
416     }
417
418     /// Returns an identifier if this token is an identifier.
419     pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
420         match self.kind {
421             Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)),
422             Interpolated(ref nt) => match **nt {
423                 NtIdent(ident, is_raw) => Some((ident, is_raw)),
424                 _ => None,
425             },
426             _ => None,
427         }
428     }
429
430     /// Returns a lifetime identifier if this token is a lifetime.
431     pub fn lifetime(&self) -> Option<ast::Ident> {
432         match self.kind {
433             Lifetime(name) => Some(ast::Ident::new(name, self.span)),
434             Interpolated(ref nt) => match **nt {
435                 NtLifetime(ident) => Some(ident),
436                 _ => None,
437             },
438             _ => None,
439         }
440     }
441
442     /// Returns `true` if the token is an identifier.
443     pub fn is_ident(&self) -> bool {
444         self.ident().is_some()
445     }
446
447     /// Returns `true` if the token is a lifetime.
448     pub fn is_lifetime(&self) -> bool {
449         self.lifetime().is_some()
450     }
451
452     /// Returns `true` if the token is a identifier whose name is the given
453     /// string slice.
454     pub fn is_ident_named(&self, name: Symbol) -> bool {
455         self.ident().map_or(false, |(ident, _)| ident.name == name)
456     }
457
458     /// Returns `true` if the token is an interpolated path.
459     fn is_path(&self) -> bool {
460         if let Interpolated(ref nt) = self.kind {
461             if let NtPath(..) = **nt {
462                 return true;
463             }
464         }
465         false
466     }
467
468     /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
469     /// That is, is this a pre-parsed expression dropped into the token stream
470     /// (which happens while parsing the result of macro expansion)?
471     pub fn is_whole_expr(&self) -> bool {
472         if let Interpolated(ref nt) = self.kind {
473             if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt {
474                 return true;
475             }
476         }
477
478         false
479     }
480
481     /// Returns `true` if the token is either the `mut` or `const` keyword.
482     pub fn is_mutability(&self) -> bool {
483         self.is_keyword(kw::Mut) || 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
492             || self.is_qpath_start()
493             || self.is_path()
494             || self.is_path_segment_keyword()
495             || self.is_ident() && !self.is_reserved_ident()
496     }
497
498     /// Returns `true` if the token is a given keyword, `kw`.
499     pub fn is_keyword(&self, kw: Symbol) -> bool {
500         self.is_non_raw_ident_where(|id| id.name == kw)
501     }
502
503     pub fn is_path_segment_keyword(&self) -> bool {
504         self.is_non_raw_ident_where(ast::Ident::is_path_segment_keyword)
505     }
506
507     // Returns true for reserved identifiers used internally for elided lifetimes,
508     // unnamed method parameters, crate root module, error recovery etc.
509     pub fn is_special_ident(&self) -> bool {
510         self.is_non_raw_ident_where(ast::Ident::is_special)
511     }
512
513     /// Returns `true` if the token is a keyword used in the language.
514     pub fn is_used_keyword(&self) -> bool {
515         self.is_non_raw_ident_where(ast::Ident::is_used_keyword)
516     }
517
518     /// Returns `true` if the token is a keyword reserved for possible future use.
519     pub fn is_unused_keyword(&self) -> bool {
520         self.is_non_raw_ident_where(ast::Ident::is_unused_keyword)
521     }
522
523     /// Returns `true` if the token is either a special identifier or a keyword.
524     pub fn is_reserved_ident(&self) -> bool {
525         self.is_non_raw_ident_where(ast::Ident::is_reserved)
526     }
527
528     /// Returns `true` if the token is the identifier `true` or `false`.
529     pub fn is_bool_lit(&self) -> bool {
530         self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
531     }
532
533     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
534     fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool {
535         match self.ident() {
536             Some((id, false)) => pred(id),
537             _ => false,
538         }
539     }
540
541     pub fn glue(&self, joint: &Token) -> Option<Token> {
542         let kind = match self.kind {
543             Eq => match joint.kind {
544                 Eq => EqEq,
545                 Gt => FatArrow,
546                 _ => return None,
547             },
548             Lt => match joint.kind {
549                 Eq => Le,
550                 Lt => BinOp(Shl),
551                 Le => BinOpEq(Shl),
552                 BinOp(Minus) => LArrow,
553                 _ => return None,
554             },
555             Gt => match joint.kind {
556                 Eq => Ge,
557                 Gt => BinOp(Shr),
558                 Ge => BinOpEq(Shr),
559                 _ => return None,
560             },
561             Not => match joint.kind {
562                 Eq => Ne,
563                 _ => return None,
564             },
565             BinOp(op) => match joint.kind {
566                 Eq => BinOpEq(op),
567                 BinOp(And) if op == And => AndAnd,
568                 BinOp(Or) if op == Or => OrOr,
569                 Gt if op == Minus => RArrow,
570                 _ => return None,
571             },
572             Dot => match joint.kind {
573                 Dot => DotDot,
574                 DotDot => DotDotDot,
575                 _ => return None,
576             },
577             DotDot => match joint.kind {
578                 Dot => DotDotDot,
579                 Eq => DotDotEq,
580                 _ => return None,
581             },
582             Colon => match joint.kind {
583                 Colon => ModSep,
584                 _ => return None,
585             },
586             SingleQuote => match joint.kind {
587                 Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
588                 _ => return None,
589             },
590
591             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
592             | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
593             | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
594             | Lifetime(..) | Interpolated(..) | DocComment(..) | Whitespace | Comment
595             | Shebang(..) | Unknown(..) | Eof => return None,
596         };
597
598         Some(Token::new(kind, self.span.to(joint.span)))
599     }
600
601     // See comments in `Nonterminal::to_tokenstream` for why we care about
602     // *probably* equal here rather than actual equality
603     crate fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
604         if mem::discriminant(&self.kind) != mem::discriminant(&other.kind) {
605             return false;
606         }
607         match (&self.kind, &other.kind) {
608             (&Eq, &Eq)
609             | (&Lt, &Lt)
610             | (&Le, &Le)
611             | (&EqEq, &EqEq)
612             | (&Ne, &Ne)
613             | (&Ge, &Ge)
614             | (&Gt, &Gt)
615             | (&AndAnd, &AndAnd)
616             | (&OrOr, &OrOr)
617             | (&Not, &Not)
618             | (&Tilde, &Tilde)
619             | (&At, &At)
620             | (&Dot, &Dot)
621             | (&DotDot, &DotDot)
622             | (&DotDotDot, &DotDotDot)
623             | (&DotDotEq, &DotDotEq)
624             | (&Comma, &Comma)
625             | (&Semi, &Semi)
626             | (&Colon, &Colon)
627             | (&ModSep, &ModSep)
628             | (&RArrow, &RArrow)
629             | (&LArrow, &LArrow)
630             | (&FatArrow, &FatArrow)
631             | (&Pound, &Pound)
632             | (&Dollar, &Dollar)
633             | (&Question, &Question)
634             | (&Whitespace, &Whitespace)
635             | (&Comment, &Comment)
636             | (&Eof, &Eof) => true,
637
638             (&BinOp(a), &BinOp(b)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
639
640             (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
641
642             (&DocComment(a), &DocComment(b)) | (&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)) => {
648                 b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
649             }
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::AssocItem),
685     NtImplItem(ast::AssocItem),
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             }
695             (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
696             (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
697             // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
698             // correctly based on data from AST. This will prevent them from matching each other
699             // in macros. The comparison will become possible only when each nonterminal has an
700             // attached token stream from which it was parsed.
701             _ => false,
702         }
703     }
704 }
705
706 impl fmt::Debug for Nonterminal {
707     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708         match *self {
709             NtItem(..) => f.pad("NtItem(..)"),
710             NtBlock(..) => f.pad("NtBlock(..)"),
711             NtStmt(..) => f.pad("NtStmt(..)"),
712             NtPat(..) => f.pad("NtPat(..)"),
713             NtExpr(..) => f.pad("NtExpr(..)"),
714             NtTy(..) => f.pad("NtTy(..)"),
715             NtIdent(..) => f.pad("NtIdent(..)"),
716             NtLiteral(..) => f.pad("NtLiteral(..)"),
717             NtMeta(..) => f.pad("NtMeta(..)"),
718             NtPath(..) => f.pad("NtPath(..)"),
719             NtTT(..) => f.pad("NtTT(..)"),
720             NtImplItem(..) => f.pad("NtImplItem(..)"),
721             NtTraitItem(..) => f.pad("NtTraitItem(..)"),
722             NtForeignItem(..) => f.pad("NtForeignItem(..)"),
723             NtVis(..) => f.pad("NtVis(..)"),
724             NtLifetime(..) => f.pad("NtLifetime(..)"),
725         }
726     }
727 }
728
729 impl<CTX> HashStable<CTX> for Nonterminal
730 where
731     CTX: crate::HashStableContext,
732 {
733     fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
734         panic!("interpolated tokens should not be present in the HIR")
735     }
736 }