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