]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/token.rs
Make ExportedSymbols type more local because it's not supposed to be
[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::tokenstream::TokenTree;
10
11 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
12 use rustc_data_structures::sync::Lrc;
13 use rustc_macros::HashStable_Generic;
14 use rustc_span::symbol::kw;
15 use rustc_span::symbol::Symbol;
16 use rustc_span::{self, Span, DUMMY_SP};
17 use std::fmt;
18 use std::mem;
19
20 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
21 #[derive(HashStable_Generic)]
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 #[derive(HashStable_Generic)]
38 pub enum DelimToken {
39     /// A round parenthesis (i.e., `(` or `)`).
40     Paren,
41     /// A square bracket (i.e., `[` or `]`).
42     Bracket,
43     /// A curly brace (i.e., `{` or `}`).
44     Brace,
45     /// An empty delimiter.
46     NoDelim,
47 }
48
49 impl DelimToken {
50     pub fn len(self) -> usize {
51         if self == NoDelim { 0 } else { 1 }
52     }
53
54     pub fn is_empty(self) -> bool {
55         self == NoDelim
56     }
57 }
58
59 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
60 pub enum LitKind {
61     Bool, // AST only, must never appear in a `Token`
62     Byte,
63     Char,
64     Integer,
65     Float,
66     Str,
67     StrRaw(u16), // raw string delimited by `n` hash symbols
68     ByteStr,
69     ByteStrRaw(u16), // raw byte string delimited by `n` hash symbols
70     Err,
71 }
72
73 /// A literal token.
74 #[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
75 pub struct Lit {
76     pub kind: LitKind,
77     pub symbol: Symbol,
78     pub suffix: Option<Symbol>,
79 }
80
81 impl fmt::Display for Lit {
82     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83         let Lit { kind, symbol, suffix } = *self;
84         match kind {
85             Byte => write!(f, "b'{}'", symbol)?,
86             Char => write!(f, "'{}'", symbol)?,
87             Str => write!(f, "\"{}\"", symbol)?,
88             StrRaw(n) => write!(
89                 f,
90                 "r{delim}\"{string}\"{delim}",
91                 delim = "#".repeat(n as usize),
92                 string = symbol
93             )?,
94             ByteStr => write!(f, "b\"{}\"", symbol)?,
95             ByteStrRaw(n) => write!(
96                 f,
97                 "br{delim}\"{string}\"{delim}",
98                 delim = "#".repeat(n as usize),
99                 string = symbol
100             )?,
101             Integer | Float | Bool | Err => write!(f, "{}", symbol)?,
102         }
103
104         if let Some(suffix) = suffix {
105             write!(f, "{}", suffix)?;
106         }
107
108         Ok(())
109     }
110 }
111
112 impl LitKind {
113     /// An English article for the literal token kind.
114     pub fn article(self) -> &'static str {
115         match self {
116             Integer | Err => "an",
117             _ => "a",
118         }
119     }
120
121     pub fn descr(self) -> &'static str {
122         match self {
123             Bool => panic!("literal token contains `Lit::Bool`"),
124             Byte => "byte",
125             Char => "char",
126             Integer => "integer",
127             Float => "float",
128             Str | StrRaw(..) => "string",
129             ByteStr | ByteStrRaw(..) => "byte string",
130             Err => "error",
131         }
132     }
133
134     crate fn may_have_suffix(self) -> bool {
135         match self {
136             Integer | Float | Err => true,
137             _ => false,
138         }
139     }
140 }
141
142 impl Lit {
143     pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
144         Lit { kind, symbol, suffix }
145     }
146 }
147
148 pub fn ident_can_begin_expr(name: ast::Name, span: Span, is_raw: bool) -> bool {
149     let ident_token = Token::new(Ident(name, is_raw), span);
150     token_can_begin_expr(&ident_token)
151 }
152
153 pub fn token_can_begin_expr(ident_token: &Token) -> bool {
154     !ident_token.is_reserved_ident()
155         || ident_token.is_path_segment_keyword()
156         || match ident_token.kind {
157             TokenKind::Ident(ident, _) => [
158                 kw::Async,
159                 kw::Do,
160                 kw::Box,
161                 kw::Break,
162                 kw::Continue,
163                 kw::False,
164                 kw::For,
165                 kw::If,
166                 kw::Let,
167                 kw::Loop,
168                 kw::Match,
169                 kw::Move,
170                 kw::Return,
171                 kw::True,
172                 kw::Unsafe,
173                 kw::While,
174                 kw::Yield,
175                 kw::Static,
176             ]
177             .contains(&ident),
178             _ => false,
179         }
180 }
181
182 fn ident_can_begin_type(name: ast::Name, span: Span, is_raw: bool) -> bool {
183     let ident_token = Token::new(Ident(name, is_raw), span);
184
185     !ident_token.is_reserved_ident()
186         || ident_token.is_path_segment_keyword()
187         || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
188             .contains(&name)
189 }
190
191 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
192 pub enum TokenKind {
193     /* Expression-operator symbols. */
194     Eq,
195     Lt,
196     Le,
197     EqEq,
198     Ne,
199     Ge,
200     Gt,
201     AndAnd,
202     OrOr,
203     Not,
204     Tilde,
205     BinOp(BinOpToken),
206     BinOpEq(BinOpToken),
207
208     /* Structural symbols */
209     At,
210     Dot,
211     DotDot,
212     DotDotDot,
213     DotDotEq,
214     Comma,
215     Semi,
216     Colon,
217     ModSep,
218     RArrow,
219     LArrow,
220     FatArrow,
221     Pound,
222     Dollar,
223     Question,
224     /// Used by proc macros for representing lifetimes, not generated by lexer right now.
225     SingleQuote,
226     /// An opening delimiter (e.g., `{`).
227     OpenDelim(DelimToken),
228     /// A closing delimiter (e.g., `}`).
229     CloseDelim(DelimToken),
230
231     /* Literals */
232     Literal(Lit),
233
234     /* Name components */
235     Ident(ast::Name, /* is_raw */ bool),
236     Lifetime(ast::Name),
237
238     Interpolated(Lrc<Nonterminal>),
239
240     // Can be expanded into several tokens.
241     /// A doc comment.
242     DocComment(ast::Name),
243
244     // Junk. These carry no data because we don't really care about the data
245     // they *would* carry, and don't really want to allocate a new ident for
246     // them. Instead, users could extract that from the associated span.
247     /// Whitespace.
248     Whitespace,
249     /// A comment.
250     Comment,
251     Shebang(ast::Name),
252     /// A completely invalid token which should be skipped.
253     Unknown(ast::Name),
254
255     Eof,
256 }
257
258 // `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
259 #[cfg(target_arch = "x86_64")]
260 rustc_data_structures::static_assert_size!(TokenKind, 16);
261
262 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
263 pub struct Token {
264     pub kind: TokenKind,
265     pub span: Span,
266 }
267
268 impl TokenKind {
269     pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
270         Literal(Lit::new(kind, symbol, suffix))
271     }
272
273     /// Returns tokens that are likely to be typed accidentally instead of the current token.
274     /// Enables better error recovery when the wrong token is found.
275     pub fn similar_tokens(&self) -> Option<Vec<TokenKind>> {
276         match *self {
277             Comma => Some(vec![Dot, Lt, Semi]),
278             Semi => Some(vec![Colon, Comma]),
279             _ => None,
280         }
281     }
282 }
283
284 impl Token {
285     pub fn new(kind: TokenKind, span: Span) -> Self {
286         Token { kind, span }
287     }
288
289     /// Some token that will be thrown away later.
290     pub fn dummy() -> Self {
291         Token::new(TokenKind::Whitespace, DUMMY_SP)
292     }
293
294     /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
295     pub fn from_ast_ident(ident: ast::Ident) -> Self {
296         Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
297     }
298
299     /// Return this token by value and leave a dummy token in its place.
300     pub fn take(&mut self) -> Self {
301         mem::replace(self, Token::dummy())
302     }
303
304     pub fn is_op(&self) -> bool {
305         match self.kind {
306             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
307             | Lifetime(..) | Interpolated(..) | Whitespace | Comment | Shebang(..) | Eof => false,
308             _ => true,
309         }
310     }
311
312     pub fn is_like_plus(&self) -> bool {
313         match self.kind {
314             BinOp(Plus) | BinOpEq(Plus) => true,
315             _ => false,
316         }
317     }
318
319     /// Returns `true` if the token can appear at the start of an expression.
320     pub fn can_begin_expr(&self) -> bool {
321         match self.kind {
322             Ident(name, is_raw)              =>
323                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
324             OpenDelim(..)                     | // tuple, array or block
325             Literal(..)                       | // literal
326             Not                               | // operator not
327             BinOp(Minus)                      | // unary minus
328             BinOp(Star)                       | // dereference
329             BinOp(Or) | OrOr                  | // closure
330             BinOp(And)                        | // reference
331             AndAnd                            | // double reference
332             // DotDotDot is no longer supported, but we need some way to display the error
333             DotDot | DotDotDot | DotDotEq     | // range notation
334             Lt | BinOp(Shl)                   | // associated path
335             ModSep                            | // global path
336             Lifetime(..)                      | // labeled loop
337             Pound                             => true, // expression attributes
338             Interpolated(ref nt) => match **nt {
339                 NtLiteral(..) |
340                 NtIdent(..)   |
341                 NtExpr(..)    |
342                 NtBlock(..)   |
343                 NtPath(..)    |
344                 NtLifetime(..) => true,
345                 _ => false,
346             },
347             _ => false,
348         }
349     }
350
351     /// Returns `true` if the token can appear at the start of a type.
352     pub fn can_begin_type(&self) -> bool {
353         match self.kind {
354             Ident(name, is_raw)        =>
355                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
356             OpenDelim(Paren)            | // tuple
357             OpenDelim(Bracket)          | // array
358             Not                         | // never
359             BinOp(Star)                 | // raw pointer
360             BinOp(And)                  | // reference
361             AndAnd                      | // double reference
362             Question                    | // maybe bound in trait object
363             Lifetime(..)                | // lifetime bound in trait object
364             Lt | BinOp(Shl)             | // associated path
365             ModSep                      => true, // global path
366             Interpolated(ref nt) => match **nt {
367                 NtIdent(..) | NtTy(..) | NtPath(..) | NtLifetime(..) => true,
368                 _ => false,
369             },
370             _ => false,
371         }
372     }
373
374     /// Returns `true` if the token can appear at the start of a const param.
375     pub fn can_begin_const_arg(&self) -> bool {
376         match self.kind {
377             OpenDelim(Brace) => true,
378             Interpolated(ref nt) => match **nt {
379                 NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
380                 _ => false,
381             },
382             _ => self.can_begin_literal_or_bool(),
383         }
384     }
385
386     /// Returns `true` if the token can appear at the start of a generic bound.
387     pub fn can_begin_bound(&self) -> bool {
388         self.is_path_start()
389             || self.is_lifetime()
390             || self.is_keyword(kw::For)
391             || self == &Question
392             || 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) || self.is_keyword(kw::Const)
483     }
484
485     pub fn is_qpath_start(&self) -> bool {
486         self == &Lt || self == &BinOp(Shl)
487     }
488
489     pub fn is_path_start(&self) -> bool {
490         self == &ModSep
491             || self.is_qpath_start()
492             || self.is_path()
493             || self.is_path_segment_keyword()
494             || 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     pub 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     pub 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     pub 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     pub 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     pub 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     pub 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(..) | Literal(..) | Ident(..)
593             | Lifetime(..) | Interpolated(..) | DocComment(..) | Whitespace | Comment
594             | 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)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
638
639             (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
640
641             (&DocComment(a), &DocComment(b)) | (&Shebang(a), &Shebang(b)) => a == b,
642
643             (&Literal(a), &Literal(b)) => a == b,
644
645             (&Lifetime(a), &Lifetime(b)) => a == b,
646             (&Ident(a, b), &Ident(c, d)) => {
647                 b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
648             }
649
650             (&Interpolated(_), &Interpolated(_)) => false,
651
652             _ => panic!("forgot to add a token?"),
653         }
654     }
655 }
656
657 impl PartialEq<TokenKind> for Token {
658     fn eq(&self, rhs: &TokenKind) -> bool {
659         self.kind == *rhs
660     }
661 }
662
663 #[derive(Clone, RustcEncodable, RustcDecodable)]
664 /// For interpolation during macro expansion.
665 pub enum Nonterminal {
666     NtItem(P<ast::Item>),
667     NtBlock(P<ast::Block>),
668     NtStmt(ast::Stmt),
669     NtPat(P<ast::Pat>),
670     NtExpr(P<ast::Expr>),
671     NtTy(P<ast::Ty>),
672     NtIdent(ast::Ident, /* is_raw */ bool),
673     NtLifetime(ast::Ident),
674     NtLiteral(P<ast::Expr>),
675     /// Stuff inside brackets for attributes
676     NtMeta(ast::AttrItem),
677     NtPath(ast::Path),
678     NtVis(ast::Visibility),
679     NtTT(TokenTree),
680     // Used only for passing items to proc macro attributes (they are not
681     // strictly necessary for that, `Annotatable` can be converted into
682     // tokens directly, but doing that naively regresses pretty-printing).
683     NtTraitItem(ast::AssocItem),
684     NtImplItem(ast::AssocItem),
685     NtForeignItem(ast::ForeignItem),
686 }
687
688 impl PartialEq for Nonterminal {
689     fn eq(&self, rhs: &Self) -> bool {
690         match (self, rhs) {
691             (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
692                 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
693             }
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 }
727
728 impl<CTX> HashStable<CTX> for Nonterminal
729 where
730     CTX: crate::HashStableContext,
731 {
732     fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
733         panic!("interpolated tokens should not be present in the HIR")
734     }
735 }