]> git.lizzy.rs Git - rust.git/blob - src/librustc_ast/token.rs
Rollup merge of #70038 - DutchGhost:const-forget-tests, r=RalfJung
[rust.git] / src / librustc_ast / 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::borrow::Cow;
18 use std::{fmt, 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
151     !ident_token.is_reserved_ident()
152         || ident_token.is_path_segment_keyword()
153         || [
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         ]
173         .contains(&name)
174 }
175
176 fn ident_can_begin_type(name: ast::Name, span: Span, is_raw: bool) -> bool {
177     let ident_token = Token::new(Ident(name, is_raw), span);
178
179     !ident_token.is_reserved_ident()
180         || ident_token.is_path_segment_keyword()
181         || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
182             .contains(&name)
183 }
184
185 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
186 pub enum TokenKind {
187     /* Expression-operator symbols. */
188     Eq,
189     Lt,
190     Le,
191     EqEq,
192     Ne,
193     Ge,
194     Gt,
195     AndAnd,
196     OrOr,
197     Not,
198     Tilde,
199     BinOp(BinOpToken),
200     BinOpEq(BinOpToken),
201
202     /* Structural symbols */
203     At,
204     Dot,
205     DotDot,
206     DotDotDot,
207     DotDotEq,
208     Comma,
209     Semi,
210     Colon,
211     ModSep,
212     RArrow,
213     LArrow,
214     FatArrow,
215     Pound,
216     Dollar,
217     Question,
218     /// Used by proc macros for representing lifetimes, not generated by lexer right now.
219     SingleQuote,
220     /// An opening delimiter (e.g., `{`).
221     OpenDelim(DelimToken),
222     /// A closing delimiter (e.g., `}`).
223     CloseDelim(DelimToken),
224
225     /* Literals */
226     Literal(Lit),
227
228     /// Identifier token.
229     /// Do not forget about `NtIdent` when you want to match on identifiers.
230     /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
231     /// treat regular and interpolated identifiers in the same way.
232     Ident(ast::Name, /* is_raw */ bool),
233     /// Lifetime identifier token.
234     /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
235     /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
236     /// treat regular and interpolated lifetime identifiers in the same way.
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     // An approximation to proc-macro-style single-character operators used by rustc parser.
275     // If the operator token can be broken into two tokens, the first of which is single-character,
276     // then this function performs that operation, otherwise it returns `None`.
277     pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> {
278         Some(match *self {
279             Le => (Lt, Eq),
280             EqEq => (Eq, Eq),
281             Ne => (Not, Eq),
282             Ge => (Gt, Eq),
283             AndAnd => (BinOp(And), BinOp(And)),
284             OrOr => (BinOp(Or), BinOp(Or)),
285             BinOp(Shl) => (Lt, Lt),
286             BinOp(Shr) => (Gt, Gt),
287             BinOpEq(Plus) => (BinOp(Plus), Eq),
288             BinOpEq(Minus) => (BinOp(Minus), Eq),
289             BinOpEq(Star) => (BinOp(Star), Eq),
290             BinOpEq(Slash) => (BinOp(Slash), Eq),
291             BinOpEq(Percent) => (BinOp(Percent), Eq),
292             BinOpEq(Caret) => (BinOp(Caret), Eq),
293             BinOpEq(And) => (BinOp(And), Eq),
294             BinOpEq(Or) => (BinOp(Or), Eq),
295             BinOpEq(Shl) => (Lt, Le),
296             BinOpEq(Shr) => (Gt, Ge),
297             DotDot => (Dot, Dot),
298             DotDotDot => (Dot, DotDot),
299             ModSep => (Colon, Colon),
300             RArrow => (BinOp(Minus), Gt),
301             LArrow => (Lt, BinOp(Minus)),
302             FatArrow => (Eq, Gt),
303             _ => return None,
304         })
305     }
306
307     /// Returns tokens that are likely to be typed accidentally instead of the current token.
308     /// Enables better error recovery when the wrong token is found.
309     pub fn similar_tokens(&self) -> Option<Vec<TokenKind>> {
310         match *self {
311             Comma => Some(vec![Dot, Lt, Semi]),
312             Semi => Some(vec![Colon, Comma]),
313             _ => None,
314         }
315     }
316 }
317
318 impl Token {
319     pub fn new(kind: TokenKind, span: Span) -> Self {
320         Token { kind, span }
321     }
322
323     /// Some token that will be thrown away later.
324     pub fn dummy() -> Self {
325         Token::new(TokenKind::Whitespace, DUMMY_SP)
326     }
327
328     /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
329     pub fn from_ast_ident(ident: ast::Ident) -> Self {
330         Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
331     }
332
333     /// Return this token by value and leave a dummy token in its place.
334     pub fn take(&mut self) -> Self {
335         mem::replace(self, Token::dummy())
336     }
337
338     /// For interpolated tokens, returns a span of the fragment to which the interpolated
339     /// token refers. For all other tokens this is just a regular span.
340     /// It is particularly important to use this for identifiers and lifetimes
341     /// for which spans affect name resolution and edition checks.
342     /// Note that keywords are also identifiers, so they should use this
343     /// if they keep spans or perform edition checks.
344     pub fn uninterpolated_span(&self) -> Span {
345         match &self.kind {
346             Interpolated(nt) => nt.span(),
347             _ => self.span,
348         }
349     }
350
351     pub fn is_op(&self) -> bool {
352         match self.kind {
353             OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
354             | Lifetime(..) | Interpolated(..) | Whitespace | Comment | Shebang(..) | Eof => false,
355             _ => true,
356         }
357     }
358
359     pub fn is_like_plus(&self) -> bool {
360         match self.kind {
361             BinOp(Plus) | BinOpEq(Plus) => true,
362             _ => false,
363         }
364     }
365
366     /// Returns `true` if the token can appear at the start of an expression.
367     pub fn can_begin_expr(&self) -> bool {
368         match self.uninterpolate().kind {
369             Ident(name, is_raw)              =>
370                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
371             OpenDelim(..)                     | // tuple, array or block
372             Literal(..)                       | // literal
373             Not                               | // operator not
374             BinOp(Minus)                      | // unary minus
375             BinOp(Star)                       | // dereference
376             BinOp(Or) | OrOr                  | // closure
377             BinOp(And)                        | // reference
378             AndAnd                            | // double reference
379             // DotDotDot is no longer supported, but we need some way to display the error
380             DotDot | DotDotDot | DotDotEq     | // range notation
381             Lt | BinOp(Shl)                   | // associated path
382             ModSep                            | // global path
383             Lifetime(..)                      | // labeled loop
384             Pound                             => true, // expression attributes
385             Interpolated(ref nt) => match **nt {
386                 NtLiteral(..) |
387                 NtExpr(..)    |
388                 NtBlock(..)   |
389                 NtPath(..) => true,
390                 _ => false,
391             },
392             _ => false,
393         }
394     }
395
396     /// Returns `true` if the token can appear at the start of a type.
397     pub fn can_begin_type(&self) -> bool {
398         match self.uninterpolate().kind {
399             Ident(name, is_raw)        =>
400                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
401             OpenDelim(Paren)            | // tuple
402             OpenDelim(Bracket)          | // array
403             Not                         | // never
404             BinOp(Star)                 | // raw pointer
405             BinOp(And)                  | // reference
406             AndAnd                      | // double reference
407             Question                    | // maybe bound in trait object
408             Lifetime(..)                | // lifetime bound in trait object
409             Lt | BinOp(Shl)             | // associated path
410             ModSep                      => true, // global path
411             Interpolated(ref nt) => match **nt {
412                 NtTy(..) | NtPath(..) => true,
413                 _ => false,
414             },
415             _ => false,
416         }
417     }
418
419     /// Returns `true` if the token can appear at the start of a const param.
420     pub fn can_begin_const_arg(&self) -> bool {
421         match self.kind {
422             OpenDelim(Brace) => true,
423             Interpolated(ref nt) => match **nt {
424                 NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
425                 _ => false,
426             },
427             _ => self.can_begin_literal_or_bool(),
428         }
429     }
430
431     /// Returns `true` if the token can appear at the start of a generic bound.
432     pub fn can_begin_bound(&self) -> bool {
433         self.is_path_start()
434             || self.is_lifetime()
435             || self.is_keyword(kw::For)
436             || self == &Question
437             || self == &OpenDelim(Paren)
438     }
439
440     /// Returns `true` if the token is any literal
441     pub fn is_lit(&self) -> bool {
442         match self.kind {
443             Literal(..) => true,
444             _ => false,
445         }
446     }
447
448     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
449     /// for example a '-42', or one of the boolean idents).
450     ///
451     /// Keep this in sync with `Lit::from_token`.
452     pub fn can_begin_literal_or_bool(&self) -> bool {
453         match self.uninterpolate().kind {
454             Literal(..) | BinOp(Minus) => true,
455             Ident(name, false) if name.is_bool_lit() => true,
456             Interpolated(ref nt) => match &**nt {
457                 NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)),
458                 _ => false,
459             },
460             _ => false,
461         }
462     }
463
464     // A convenience function for matching on identifiers during parsing.
465     // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
466     // into the regular identifier or lifetime token it refers to,
467     // otherwise returns the original token.
468     pub fn uninterpolate(&self) -> Cow<'_, Token> {
469         match &self.kind {
470             Interpolated(nt) => match **nt {
471                 NtIdent(ident, is_raw) => {
472                     Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
473                 }
474                 NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
475                 _ => Cow::Borrowed(self),
476             },
477             _ => Cow::Borrowed(self),
478         }
479     }
480
481     /// Returns an identifier if this token is an identifier.
482     pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
483         let token = self.uninterpolate();
484         match token.kind {
485             Ident(name, is_raw) => Some((ast::Ident::new(name, token.span), is_raw)),
486             _ => None,
487         }
488     }
489
490     /// Returns a lifetime identifier if this token is a lifetime.
491     pub fn lifetime(&self) -> Option<ast::Ident> {
492         let token = self.uninterpolate();
493         match token.kind {
494             Lifetime(name) => Some(ast::Ident::new(name, token.span)),
495             _ => None,
496         }
497     }
498
499     /// Returns `true` if the token is an identifier.
500     pub fn is_ident(&self) -> bool {
501         self.ident().is_some()
502     }
503
504     /// Returns `true` if the token is a lifetime.
505     pub fn is_lifetime(&self) -> bool {
506         self.lifetime().is_some()
507     }
508
509     /// Returns `true` if the token is a identifier whose name is the given
510     /// string slice.
511     pub fn is_ident_named(&self, name: Symbol) -> bool {
512         self.ident().map_or(false, |(ident, _)| ident.name == name)
513     }
514
515     /// Returns `true` if the token is an interpolated path.
516     fn is_path(&self) -> bool {
517         if let Interpolated(ref nt) = self.kind {
518             if let NtPath(..) = **nt {
519                 return true;
520             }
521         }
522         false
523     }
524
525     /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
526     /// That is, is this a pre-parsed expression dropped into the token stream
527     /// (which happens while parsing the result of macro expansion)?
528     pub fn is_whole_expr(&self) -> bool {
529         if let Interpolated(ref nt) = self.kind {
530             if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt {
531                 return true;
532             }
533         }
534
535         false
536     }
537
538     // Is the token an interpolated block (`$b:block`)?
539     pub fn is_whole_block(&self) -> bool {
540         if let Interpolated(ref nt) = self.kind {
541             if let NtBlock(..) = **nt {
542                 return true;
543             }
544         }
545         false
546     }
547
548     /// Returns `true` if the token is either the `mut` or `const` keyword.
549     pub fn is_mutability(&self) -> bool {
550         self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
551     }
552
553     pub fn is_qpath_start(&self) -> bool {
554         self == &Lt || self == &BinOp(Shl)
555     }
556
557     pub fn is_path_start(&self) -> bool {
558         self == &ModSep
559             || self.is_qpath_start()
560             || self.is_path()
561             || self.is_path_segment_keyword()
562             || self.is_ident() && !self.is_reserved_ident()
563     }
564
565     /// Returns `true` if the token is a given keyword, `kw`.
566     pub fn is_keyword(&self, kw: Symbol) -> bool {
567         self.is_non_raw_ident_where(|id| id.name == kw)
568     }
569
570     pub fn is_path_segment_keyword(&self) -> bool {
571         self.is_non_raw_ident_where(ast::Ident::is_path_segment_keyword)
572     }
573
574     // Returns true for reserved identifiers used internally for elided lifetimes,
575     // unnamed method parameters, crate root module, error recovery etc.
576     pub fn is_special_ident(&self) -> bool {
577         self.is_non_raw_ident_where(ast::Ident::is_special)
578     }
579
580     /// Returns `true` if the token is a keyword used in the language.
581     pub fn is_used_keyword(&self) -> bool {
582         self.is_non_raw_ident_where(ast::Ident::is_used_keyword)
583     }
584
585     /// Returns `true` if the token is a keyword reserved for possible future use.
586     pub fn is_unused_keyword(&self) -> bool {
587         self.is_non_raw_ident_where(ast::Ident::is_unused_keyword)
588     }
589
590     /// Returns `true` if the token is either a special identifier or a keyword.
591     pub fn is_reserved_ident(&self) -> bool {
592         self.is_non_raw_ident_where(ast::Ident::is_reserved)
593     }
594
595     /// Returns `true` if the token is the identifier `true` or `false`.
596     pub fn is_bool_lit(&self) -> bool {
597         self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
598     }
599
600     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
601     pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(ast::Ident) -> bool) -> bool {
602         match self.ident() {
603             Some((id, false)) => pred(id),
604             _ => false,
605         }
606     }
607
608     pub fn glue(&self, joint: &Token) -> Option<Token> {
609         let kind = match self.kind {
610             Eq => match joint.kind {
611                 Eq => EqEq,
612                 Gt => FatArrow,
613                 _ => return None,
614             },
615             Lt => match joint.kind {
616                 Eq => Le,
617                 Lt => BinOp(Shl),
618                 Le => BinOpEq(Shl),
619                 BinOp(Minus) => LArrow,
620                 _ => return None,
621             },
622             Gt => match joint.kind {
623                 Eq => Ge,
624                 Gt => BinOp(Shr),
625                 Ge => BinOpEq(Shr),
626                 _ => return None,
627             },
628             Not => match joint.kind {
629                 Eq => Ne,
630                 _ => return None,
631             },
632             BinOp(op) => match joint.kind {
633                 Eq => BinOpEq(op),
634                 BinOp(And) if op == And => AndAnd,
635                 BinOp(Or) if op == Or => OrOr,
636                 Gt if op == Minus => RArrow,
637                 _ => return None,
638             },
639             Dot => match joint.kind {
640                 Dot => DotDot,
641                 DotDot => DotDotDot,
642                 _ => return None,
643             },
644             DotDot => match joint.kind {
645                 Dot => DotDotDot,
646                 Eq => DotDotEq,
647                 _ => return None,
648             },
649             Colon => match joint.kind {
650                 Colon => ModSep,
651                 _ => return None,
652             },
653             SingleQuote => match joint.kind {
654                 Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
655                 _ => return None,
656             },
657
658             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
659             | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
660             | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
661             | Lifetime(..) | Interpolated(..) | DocComment(..) | Whitespace | Comment
662             | Shebang(..) | Unknown(..) | Eof => return None,
663         };
664
665         Some(Token::new(kind, self.span.to(joint.span)))
666     }
667
668     // See comments in `Nonterminal::to_tokenstream` for why we care about
669     // *probably* equal here rather than actual equality
670     crate fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
671         if mem::discriminant(&self.kind) != mem::discriminant(&other.kind) {
672             return false;
673         }
674         match (&self.kind, &other.kind) {
675             (&Eq, &Eq)
676             | (&Lt, &Lt)
677             | (&Le, &Le)
678             | (&EqEq, &EqEq)
679             | (&Ne, &Ne)
680             | (&Ge, &Ge)
681             | (&Gt, &Gt)
682             | (&AndAnd, &AndAnd)
683             | (&OrOr, &OrOr)
684             | (&Not, &Not)
685             | (&Tilde, &Tilde)
686             | (&At, &At)
687             | (&Dot, &Dot)
688             | (&DotDot, &DotDot)
689             | (&DotDotDot, &DotDotDot)
690             | (&DotDotEq, &DotDotEq)
691             | (&Comma, &Comma)
692             | (&Semi, &Semi)
693             | (&Colon, &Colon)
694             | (&ModSep, &ModSep)
695             | (&RArrow, &RArrow)
696             | (&LArrow, &LArrow)
697             | (&FatArrow, &FatArrow)
698             | (&Pound, &Pound)
699             | (&Dollar, &Dollar)
700             | (&Question, &Question)
701             | (&Whitespace, &Whitespace)
702             | (&Comment, &Comment)
703             | (&Eof, &Eof) => true,
704
705             (&BinOp(a), &BinOp(b)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
706
707             (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
708
709             (&DocComment(a), &DocComment(b)) | (&Shebang(a), &Shebang(b)) => a == b,
710
711             (&Literal(a), &Literal(b)) => a == b,
712
713             (&Lifetime(a), &Lifetime(b)) => a == b,
714             (&Ident(a, b), &Ident(c, d)) => {
715                 b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
716             }
717
718             (&Interpolated(_), &Interpolated(_)) => false,
719
720             _ => panic!("forgot to add a token?"),
721         }
722     }
723 }
724
725 impl PartialEq<TokenKind> for Token {
726     fn eq(&self, rhs: &TokenKind) -> bool {
727         self.kind == *rhs
728     }
729 }
730
731 #[derive(Clone, RustcEncodable, RustcDecodable)]
732 /// For interpolation during macro expansion.
733 pub enum Nonterminal {
734     NtItem(P<ast::Item>),
735     NtBlock(P<ast::Block>),
736     NtStmt(ast::Stmt),
737     NtPat(P<ast::Pat>),
738     NtExpr(P<ast::Expr>),
739     NtTy(P<ast::Ty>),
740     NtIdent(ast::Ident, /* is_raw */ bool),
741     NtLifetime(ast::Ident),
742     NtLiteral(P<ast::Expr>),
743     /// Stuff inside brackets for attributes
744     NtMeta(P<ast::AttrItem>),
745     NtPath(ast::Path),
746     NtVis(ast::Visibility),
747     NtTT(TokenTree),
748 }
749
750 // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
751 #[cfg(target_arch = "x86_64")]
752 rustc_data_structures::static_assert_size!(Nonterminal, 40);
753
754 impl Nonterminal {
755     fn span(&self) -> Span {
756         match self {
757             NtItem(item) => item.span,
758             NtBlock(block) => block.span,
759             NtStmt(stmt) => stmt.span,
760             NtPat(pat) => pat.span,
761             NtExpr(expr) | NtLiteral(expr) => expr.span,
762             NtTy(ty) => ty.span,
763             NtIdent(ident, _) | NtLifetime(ident) => ident.span,
764             NtMeta(attr_item) => attr_item.span(),
765             NtPath(path) => path.span,
766             NtVis(vis) => vis.span,
767             NtTT(tt) => tt.span(),
768         }
769     }
770 }
771
772 impl PartialEq for Nonterminal {
773     fn eq(&self, rhs: &Self) -> bool {
774         match (self, rhs) {
775             (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
776                 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
777             }
778             (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
779             (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
780             // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
781             // correctly based on data from AST. This will prevent them from matching each other
782             // in macros. The comparison will become possible only when each nonterminal has an
783             // attached token stream from which it was parsed.
784             _ => false,
785         }
786     }
787 }
788
789 impl fmt::Debug for Nonterminal {
790     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
791         match *self {
792             NtItem(..) => f.pad("NtItem(..)"),
793             NtBlock(..) => f.pad("NtBlock(..)"),
794             NtStmt(..) => f.pad("NtStmt(..)"),
795             NtPat(..) => f.pad("NtPat(..)"),
796             NtExpr(..) => f.pad("NtExpr(..)"),
797             NtTy(..) => f.pad("NtTy(..)"),
798             NtIdent(..) => f.pad("NtIdent(..)"),
799             NtLiteral(..) => f.pad("NtLiteral(..)"),
800             NtMeta(..) => f.pad("NtMeta(..)"),
801             NtPath(..) => f.pad("NtPath(..)"),
802             NtTT(..) => f.pad("NtTT(..)"),
803             NtVis(..) => f.pad("NtVis(..)"),
804             NtLifetime(..) => f.pad("NtLifetime(..)"),
805         }
806     }
807 }
808
809 impl<CTX> HashStable<CTX> for Nonterminal
810 where
811     CTX: crate::HashStableContext,
812 {
813     fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
814         panic!("interpolated tokens should not be present in the HIR")
815     }
816 }