]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast/src/token.rs
Rollup merge of #100559 - nnethercote:parser-simplifications, r=compiler-errors
[rust.git] / compiler / rustc_ast / src / token.rs
1 pub use BinOpToken::*;
2 pub use LitKind::*;
3 pub use Nonterminal::*;
4 pub use TokenKind::*;
5
6 use crate::ast;
7 use crate::ptr::P;
8
9 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
10 use rustc_data_structures::sync::Lrc;
11 use rustc_macros::HashStable_Generic;
12 use rustc_span::symbol::{kw, sym};
13 use rustc_span::symbol::{Ident, Symbol};
14 use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
15 use std::borrow::Cow;
16 use std::{fmt, mem};
17
18 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
19 pub enum CommentKind {
20     Line,
21     Block,
22 }
23
24 #[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)]
25 #[derive(HashStable_Generic)]
26 pub enum BinOpToken {
27     Plus,
28     Minus,
29     Star,
30     Slash,
31     Percent,
32     Caret,
33     And,
34     Or,
35     Shl,
36     Shr,
37 }
38
39 /// Describes how a sequence of token trees is delimited.
40 /// Cannot use `proc_macro::Delimiter` directly because this
41 /// structure should implement some additional traits.
42 /// The `None` variant is also renamed to `Invisible` to be
43 /// less confusing and better convey the semantics.
44 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
45 #[derive(Encodable, Decodable, Hash, HashStable_Generic)]
46 pub enum Delimiter {
47     /// `( ... )`
48     Parenthesis,
49     /// `{ ... }`
50     Brace,
51     /// `[ ... ]`
52     Bracket,
53     /// `Ø ... Ø`
54     /// An invisible delimiter, that may, for example, appear around tokens coming from a
55     /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
56     /// `$var * 3` where `$var` is `1 + 2`.
57     /// Invisible delimiters might not survive roundtrip of a token stream through a string.
58     Invisible,
59 }
60
61 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
62 pub enum LitKind {
63     Bool, // AST only, must never appear in a `Token`
64     Byte,
65     Char,
66     Integer,
67     Float,
68     Str,
69     StrRaw(u8), // raw string delimited by `n` hash symbols
70     ByteStr,
71     ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols
72     Err,
73 }
74
75 /// A literal token.
76 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
77 pub struct Lit {
78     pub kind: LitKind,
79     pub symbol: Symbol,
80     pub suffix: Option<Symbol>,
81 }
82
83 impl fmt::Display for Lit {
84     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85         let Lit { kind, symbol, suffix } = *self;
86         match kind {
87             Byte => write!(f, "b'{}'", symbol)?,
88             Char => write!(f, "'{}'", symbol)?,
89             Str => write!(f, "\"{}\"", symbol)?,
90             StrRaw(n) => write!(
91                 f,
92                 "r{delim}\"{string}\"{delim}",
93                 delim = "#".repeat(n as usize),
94                 string = symbol
95             )?,
96             ByteStr => write!(f, "b\"{}\"", symbol)?,
97             ByteStrRaw(n) => write!(
98                 f,
99                 "br{delim}\"{string}\"{delim}",
100                 delim = "#".repeat(n as usize),
101                 string = symbol
102             )?,
103             Integer | Float | Bool | Err => write!(f, "{}", symbol)?,
104         }
105
106         if let Some(suffix) = suffix {
107             write!(f, "{}", suffix)?;
108         }
109
110         Ok(())
111     }
112 }
113
114 impl LitKind {
115     /// An English article for the literal token kind.
116     pub fn article(self) -> &'static str {
117         match self {
118             Integer | Err => "an",
119             _ => "a",
120         }
121     }
122
123     pub fn descr(self) -> &'static str {
124         match self {
125             Bool => panic!("literal token contains `Lit::Bool`"),
126             Byte => "byte",
127             Char => "char",
128             Integer => "integer",
129             Float => "float",
130             Str | StrRaw(..) => "string",
131             ByteStr | ByteStrRaw(..) => "byte string",
132             Err => "error",
133         }
134     }
135
136     pub(crate) fn may_have_suffix(self) -> bool {
137         matches!(self, Integer | Float | Err)
138     }
139 }
140
141 impl Lit {
142     pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
143         Lit { kind, symbol, suffix }
144     }
145 }
146
147 pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
148     let ident_token = Token::new(Ident(name, is_raw), span);
149
150     !ident_token.is_reserved_ident()
151         || ident_token.is_path_segment_keyword()
152         || [
153             kw::Async,
154             kw::Do,
155             kw::Box,
156             kw::Break,
157             kw::Const,
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::Try,
169             kw::Unsafe,
170             kw::While,
171             kw::Yield,
172             kw::Static,
173         ]
174         .contains(&name)
175 }
176
177 fn ident_can_begin_type(name: Symbol, 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         || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
183             .contains(&name)
184 }
185
186 #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
187 pub enum TokenKind {
188     /* Expression-operator symbols. */
189     Eq,
190     Lt,
191     Le,
192     EqEq,
193     Ne,
194     Ge,
195     Gt,
196     AndAnd,
197     OrOr,
198     Not,
199     Tilde,
200     BinOp(BinOpToken),
201     BinOpEq(BinOpToken),
202
203     /* Structural symbols */
204     At,
205     Dot,
206     DotDot,
207     DotDotDot,
208     DotDotEq,
209     Comma,
210     Semi,
211     Colon,
212     ModSep,
213     RArrow,
214     LArrow,
215     FatArrow,
216     Pound,
217     Dollar,
218     Question,
219     /// Used by proc macros for representing lifetimes, not generated by lexer right now.
220     SingleQuote,
221     /// An opening delimiter (e.g., `{`).
222     OpenDelim(Delimiter),
223     /// A closing delimiter (e.g., `}`).
224     CloseDelim(Delimiter),
225
226     /* Literals */
227     Literal(Lit),
228
229     /// Identifier token.
230     /// Do not forget about `NtIdent` when you want to match on identifiers.
231     /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
232     /// treat regular and interpolated identifiers in the same way.
233     Ident(Symbol, /* is_raw */ bool),
234     /// Lifetime identifier token.
235     /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
236     /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
237     /// treat regular and interpolated lifetime identifiers in the same way.
238     Lifetime(Symbol),
239
240     /// An embedded AST node, as produced by a macro. This only exists for
241     /// historical reasons. We'd like to get rid of it, for multiple reasons.
242     /// - It's conceptually very strange. Saying a token can contain an AST
243     ///   node is like saying, in natural language, that a word can contain a
244     ///   sentence.
245     /// - It requires special handling in a bunch of places in the parser.
246     /// - It prevents `Token` from implementing `Copy`.
247     /// It adds complexity and likely slows things down. Please don't add new
248     /// occurrences of this token kind!
249     Interpolated(Lrc<Nonterminal>),
250
251     /// A doc comment token.
252     /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
253     /// similarly to symbols in string literal tokens.
254     DocComment(CommentKind, ast::AttrStyle, Symbol),
255
256     Eof,
257 }
258
259 // `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
260 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
261 rustc_data_structures::static_assert_size!(TokenKind, 16);
262
263 #[derive(Clone, PartialEq, Encodable, Decodable, 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             FatArrow => Some(vec![Eq, RArrow]),
314             _ => None,
315         }
316     }
317
318     pub fn should_end_const_arg(&self) -> bool {
319         matches!(self, Gt | Ge | BinOp(Shr) | BinOpEq(Shr))
320     }
321 }
322
323 impl Token {
324     pub fn new(kind: TokenKind, span: Span) -> Self {
325         Token { kind, span }
326     }
327
328     /// Some token that will be thrown away later.
329     pub fn dummy() -> Self {
330         Token::new(TokenKind::Question, DUMMY_SP)
331     }
332
333     /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary.
334     pub fn from_ast_ident(ident: Ident) -> Self {
335         Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
336     }
337
338     /// Return this token by value and leave a dummy token in its place.
339     pub fn take(&mut self) -> Self {
340         mem::replace(self, Token::dummy())
341     }
342
343     /// For interpolated tokens, returns a span of the fragment to which the interpolated
344     /// token refers. For all other tokens this is just a regular span.
345     /// It is particularly important to use this for identifiers and lifetimes
346     /// for which spans affect name resolution and edition checks.
347     /// Note that keywords are also identifiers, so they should use this
348     /// if they keep spans or perform edition checks.
349     pub fn uninterpolated_span(&self) -> Span {
350         match &self.kind {
351             Interpolated(nt) => nt.span(),
352             _ => self.span,
353         }
354     }
355
356     pub fn is_op(&self) -> bool {
357         !matches!(
358             self.kind,
359             OpenDelim(..)
360                 | CloseDelim(..)
361                 | Literal(..)
362                 | DocComment(..)
363                 | Ident(..)
364                 | Lifetime(..)
365                 | Interpolated(..)
366                 | Eof
367         )
368     }
369
370     pub fn is_like_plus(&self) -> bool {
371         matches!(self.kind, BinOp(Plus) | BinOpEq(Plus))
372     }
373
374     /// Returns `true` if the token can appear at the start of an expression.
375     pub fn can_begin_expr(&self) -> bool {
376         match self.uninterpolate().kind {
377             Ident(name, is_raw)              =>
378                 ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
379             OpenDelim(..)                     | // tuple, array or block
380             Literal(..)                       | // literal
381             Not                               | // operator not
382             BinOp(Minus)                      | // unary minus
383             BinOp(Star)                       | // dereference
384             BinOp(Or) | OrOr                  | // closure
385             BinOp(And)                        | // reference
386             AndAnd                            | // double reference
387             // DotDotDot is no longer supported, but we need some way to display the error
388             DotDot | DotDotDot | DotDotEq     | // range notation
389             Lt | BinOp(Shl)                   | // associated path
390             ModSep                            | // global path
391             Lifetime(..)                      | // labeled loop
392             Pound                             => true, // expression attributes
393             Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
394                 NtExpr(..)    |
395                 NtBlock(..)   |
396                 NtPath(..)),
397             _ => false,
398         }
399     }
400
401     /// Returns `true` if the token can appear at the start of a type.
402     pub fn can_begin_type(&self) -> bool {
403         match self.uninterpolate().kind {
404             Ident(name, is_raw)        =>
405                 ident_can_begin_type(name, self.span, is_raw), // type name or keyword
406             OpenDelim(Delimiter::Parenthesis) | // tuple
407             OpenDelim(Delimiter::Bracket)     | // array
408             Not                         | // never
409             BinOp(Star)                 | // raw pointer
410             BinOp(And)                  | // reference
411             AndAnd                      | // double reference
412             Question                    | // maybe bound in trait object
413             Lifetime(..)                | // lifetime bound in trait object
414             Lt | BinOp(Shl)             | // associated path
415             ModSep                      => true, // global path
416             Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
417             _ => false,
418         }
419     }
420
421     /// Returns `true` if the token can appear at the start of a const param.
422     pub fn can_begin_const_arg(&self) -> bool {
423         match self.kind {
424             OpenDelim(Delimiter::Brace) => true,
425             Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
426             _ => self.can_begin_literal_maybe_minus(),
427         }
428     }
429
430     /// Returns `true` if the token can appear at the start of a generic bound.
431     pub fn can_begin_bound(&self) -> bool {
432         self.is_path_start()
433             || self.is_lifetime()
434             || self.is_keyword(kw::For)
435             || self == &Question
436             || self == &OpenDelim(Delimiter::Parenthesis)
437     }
438
439     /// Returns `true` if the token is any literal.
440     pub fn is_lit(&self) -> bool {
441         matches!(self.kind, Literal(..))
442     }
443
444     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
445     /// for example a '-42', or one of the boolean idents).
446     ///
447     /// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
448     ///
449     /// Keep this in sync with and `Lit::from_token`, excluding unary negation.
450     pub fn can_begin_literal_maybe_minus(&self) -> bool {
451         match self.uninterpolate().kind {
452             Literal(..) | BinOp(Minus) => true,
453             Ident(name, false) if name.is_bool_lit() => true,
454             Interpolated(ref nt) => match &**nt {
455                 NtLiteral(_) => true,
456                 NtExpr(e) => match &e.kind {
457                     ast::ExprKind::Lit(_) => true,
458                     ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
459                         matches!(&e.kind, ast::ExprKind::Lit(_))
460                     }
461                     _ => false,
462                 },
463                 _ => false,
464             },
465             _ => false,
466         }
467     }
468
469     // A convenience function for matching on identifiers during parsing.
470     // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
471     // into the regular identifier or lifetime token it refers to,
472     // otherwise returns the original token.
473     pub fn uninterpolate(&self) -> Cow<'_, Token> {
474         match &self.kind {
475             Interpolated(nt) => match **nt {
476                 NtIdent(ident, is_raw) => {
477                     Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
478                 }
479                 NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
480                 _ => Cow::Borrowed(self),
481             },
482             _ => Cow::Borrowed(self),
483         }
484     }
485
486     /// Returns an identifier if this token is an identifier.
487     #[inline]
488     pub fn ident(&self) -> Option<(Ident, /* is_raw */ bool)> {
489         // We avoid using `Token::uninterpolate` here because it's slow.
490         match &self.kind {
491             &Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
492             Interpolated(nt) => match **nt {
493                 NtIdent(ident, is_raw) => Some((ident, is_raw)),
494                 _ => None,
495             },
496             _ => None,
497         }
498     }
499
500     /// Returns a lifetime identifier if this token is a lifetime.
501     #[inline]
502     pub fn lifetime(&self) -> Option<Ident> {
503         // We avoid using `Token::uninterpolate` here because it's slow.
504         match &self.kind {
505             &Lifetime(name) => Some(Ident::new(name, self.span)),
506             Interpolated(nt) => match **nt {
507                 NtLifetime(ident) => Some(ident),
508                 _ => None,
509             },
510             _ => None,
511         }
512     }
513
514     /// Returns `true` if the token is an identifier.
515     pub fn is_ident(&self) -> bool {
516         self.ident().is_some()
517     }
518
519     /// Returns `true` if the token is a lifetime.
520     pub fn is_lifetime(&self) -> bool {
521         self.lifetime().is_some()
522     }
523
524     /// Returns `true` if the token is an identifier whose name is the given
525     /// string slice.
526     pub fn is_ident_named(&self, name: Symbol) -> bool {
527         self.ident().map_or(false, |(ident, _)| ident.name == name)
528     }
529
530     /// Returns `true` if the token is an interpolated path.
531     fn is_path(&self) -> bool {
532         if let Interpolated(ref nt) = self.kind && let NtPath(..) = **nt {
533             return true;
534         }
535         false
536     }
537
538     /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
539     /// That is, is this a pre-parsed expression dropped into the token stream
540     /// (which happens while parsing the result of macro expansion)?
541     pub fn is_whole_expr(&self) -> bool {
542         if let Interpolated(ref nt) = self.kind
543             && let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtBlock(_) = **nt
544         {
545             return true;
546         }
547
548         false
549     }
550
551     // Is the token an interpolated block (`$b:block`)?
552     pub fn is_whole_block(&self) -> bool {
553         if let Interpolated(ref nt) = self.kind && let NtBlock(..) = **nt {
554             return true;
555         }
556         false
557     }
558
559     /// Returns `true` if the token is either the `mut` or `const` keyword.
560     pub fn is_mutability(&self) -> bool {
561         self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
562     }
563
564     pub fn is_qpath_start(&self) -> bool {
565         self == &Lt || self == &BinOp(Shl)
566     }
567
568     pub fn is_path_start(&self) -> bool {
569         self == &ModSep
570             || self.is_qpath_start()
571             || self.is_path()
572             || self.is_path_segment_keyword()
573             || self.is_ident() && !self.is_reserved_ident()
574     }
575
576     /// Returns `true` if the token is a given keyword, `kw`.
577     pub fn is_keyword(&self, kw: Symbol) -> bool {
578         self.is_non_raw_ident_where(|id| id.name == kw)
579     }
580
581     pub fn is_path_segment_keyword(&self) -> bool {
582         self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
583     }
584
585     // Returns true for reserved identifiers used internally for elided lifetimes,
586     // unnamed method parameters, crate root module, error recovery etc.
587     pub fn is_special_ident(&self) -> bool {
588         self.is_non_raw_ident_where(Ident::is_special)
589     }
590
591     /// Returns `true` if the token is a keyword used in the language.
592     pub fn is_used_keyword(&self) -> bool {
593         self.is_non_raw_ident_where(Ident::is_used_keyword)
594     }
595
596     /// Returns `true` if the token is a keyword reserved for possible future use.
597     pub fn is_unused_keyword(&self) -> bool {
598         self.is_non_raw_ident_where(Ident::is_unused_keyword)
599     }
600
601     /// Returns `true` if the token is either a special identifier or a keyword.
602     pub fn is_reserved_ident(&self) -> bool {
603         self.is_non_raw_ident_where(Ident::is_reserved)
604     }
605
606     /// Returns `true` if the token is the identifier `true` or `false`.
607     pub fn is_bool_lit(&self) -> bool {
608         self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
609     }
610
611     pub fn is_numeric_lit(&self) -> bool {
612         matches!(
613             self.kind,
614             Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
615         )
616     }
617
618     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
619     pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
620         match self.ident() {
621             Some((id, false)) => pred(id),
622             _ => false,
623         }
624     }
625
626     pub fn glue(&self, joint: &Token) -> Option<Token> {
627         let kind = match self.kind {
628             Eq => match joint.kind {
629                 Eq => EqEq,
630                 Gt => FatArrow,
631                 _ => return None,
632             },
633             Lt => match joint.kind {
634                 Eq => Le,
635                 Lt => BinOp(Shl),
636                 Le => BinOpEq(Shl),
637                 BinOp(Minus) => LArrow,
638                 _ => return None,
639             },
640             Gt => match joint.kind {
641                 Eq => Ge,
642                 Gt => BinOp(Shr),
643                 Ge => BinOpEq(Shr),
644                 _ => return None,
645             },
646             Not => match joint.kind {
647                 Eq => Ne,
648                 _ => return None,
649             },
650             BinOp(op) => match joint.kind {
651                 Eq => BinOpEq(op),
652                 BinOp(And) if op == And => AndAnd,
653                 BinOp(Or) if op == Or => OrOr,
654                 Gt if op == Minus => RArrow,
655                 _ => return None,
656             },
657             Dot => match joint.kind {
658                 Dot => DotDot,
659                 DotDot => DotDotDot,
660                 _ => return None,
661             },
662             DotDot => match joint.kind {
663                 Dot => DotDotDot,
664                 Eq => DotDotEq,
665                 _ => return None,
666             },
667             Colon => match joint.kind {
668                 Colon => ModSep,
669                 _ => return None,
670             },
671             SingleQuote => match joint.kind {
672                 Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))),
673                 _ => return None,
674             },
675
676             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
677             | DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
678             | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
679             | Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None,
680         };
681
682         Some(Token::new(kind, self.span.to(joint.span)))
683     }
684 }
685
686 impl PartialEq<TokenKind> for Token {
687     fn eq(&self, rhs: &TokenKind) -> bool {
688         self.kind == *rhs
689     }
690 }
691
692 #[derive(Clone, Encodable, Decodable)]
693 /// For interpolation during macro expansion.
694 pub enum Nonterminal {
695     NtItem(P<ast::Item>),
696     NtBlock(P<ast::Block>),
697     NtStmt(P<ast::Stmt>),
698     NtPat(P<ast::Pat>),
699     NtExpr(P<ast::Expr>),
700     NtTy(P<ast::Ty>),
701     NtIdent(Ident, /* is_raw */ bool),
702     NtLifetime(Ident),
703     NtLiteral(P<ast::Expr>),
704     /// Stuff inside brackets for attributes
705     NtMeta(P<ast::AttrItem>),
706     NtPath(P<ast::Path>),
707     NtVis(P<ast::Visibility>),
708 }
709
710 // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
711 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
712 rustc_data_structures::static_assert_size!(Nonterminal, 16);
713
714 #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
715 pub enum NonterminalKind {
716     Item,
717     Block,
718     Stmt,
719     PatParam {
720         /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the
721         /// edition of the span. This is used for diagnostics.
722         inferred: bool,
723     },
724     PatWithOr,
725     Expr,
726     Ty,
727     Ident,
728     Lifetime,
729     Literal,
730     Meta,
731     Path,
732     Vis,
733     TT,
734 }
735
736 impl NonterminalKind {
737     /// The `edition` closure is used to get the edition for the given symbol. Doing
738     /// `span.edition()` is expensive, so we do it lazily.
739     pub fn from_symbol(
740         symbol: Symbol,
741         edition: impl FnOnce() -> Edition,
742     ) -> Option<NonterminalKind> {
743         Some(match symbol {
744             sym::item => NonterminalKind::Item,
745             sym::block => NonterminalKind::Block,
746             sym::stmt => NonterminalKind::Stmt,
747             sym::pat => match edition() {
748                 Edition::Edition2015 | Edition::Edition2018 => {
749                     NonterminalKind::PatParam { inferred: true }
750                 }
751                 Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr,
752             },
753             sym::pat_param => NonterminalKind::PatParam { inferred: false },
754             sym::expr => NonterminalKind::Expr,
755             sym::ty => NonterminalKind::Ty,
756             sym::ident => NonterminalKind::Ident,
757             sym::lifetime => NonterminalKind::Lifetime,
758             sym::literal => NonterminalKind::Literal,
759             sym::meta => NonterminalKind::Meta,
760             sym::path => NonterminalKind::Path,
761             sym::vis => NonterminalKind::Vis,
762             sym::tt => NonterminalKind::TT,
763             _ => return None,
764         })
765     }
766     fn symbol(self) -> Symbol {
767         match self {
768             NonterminalKind::Item => sym::item,
769             NonterminalKind::Block => sym::block,
770             NonterminalKind::Stmt => sym::stmt,
771             NonterminalKind::PatParam { inferred: false } => sym::pat_param,
772             NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat,
773             NonterminalKind::Expr => sym::expr,
774             NonterminalKind::Ty => sym::ty,
775             NonterminalKind::Ident => sym::ident,
776             NonterminalKind::Lifetime => sym::lifetime,
777             NonterminalKind::Literal => sym::literal,
778             NonterminalKind::Meta => sym::meta,
779             NonterminalKind::Path => sym::path,
780             NonterminalKind::Vis => sym::vis,
781             NonterminalKind::TT => sym::tt,
782         }
783     }
784 }
785
786 impl fmt::Display for NonterminalKind {
787     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
788         write!(f, "{}", self.symbol())
789     }
790 }
791
792 impl Nonterminal {
793     pub fn span(&self) -> Span {
794         match self {
795             NtItem(item) => item.span,
796             NtBlock(block) => block.span,
797             NtStmt(stmt) => stmt.span,
798             NtPat(pat) => pat.span,
799             NtExpr(expr) | NtLiteral(expr) => expr.span,
800             NtTy(ty) => ty.span,
801             NtIdent(ident, _) | NtLifetime(ident) => ident.span,
802             NtMeta(attr_item) => attr_item.span(),
803             NtPath(path) => path.span,
804             NtVis(vis) => vis.span,
805         }
806     }
807 }
808
809 impl PartialEq for Nonterminal {
810     fn eq(&self, rhs: &Self) -> bool {
811         match (self, rhs) {
812             (NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
813                 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
814             }
815             (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
816             // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
817             // correctly based on data from AST. This will prevent them from matching each other
818             // in macros. The comparison will become possible only when each nonterminal has an
819             // attached token stream from which it was parsed.
820             _ => false,
821         }
822     }
823 }
824
825 impl fmt::Debug for Nonterminal {
826     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827         match *self {
828             NtItem(..) => f.pad("NtItem(..)"),
829             NtBlock(..) => f.pad("NtBlock(..)"),
830             NtStmt(..) => f.pad("NtStmt(..)"),
831             NtPat(..) => f.pad("NtPat(..)"),
832             NtExpr(..) => f.pad("NtExpr(..)"),
833             NtTy(..) => f.pad("NtTy(..)"),
834             NtIdent(..) => f.pad("NtIdent(..)"),
835             NtLiteral(..) => f.pad("NtLiteral(..)"),
836             NtMeta(..) => f.pad("NtMeta(..)"),
837             NtPath(..) => f.pad("NtPath(..)"),
838             NtVis(..) => f.pad("NtVis(..)"),
839             NtLifetime(..) => f.pad("NtLifetime(..)"),
840         }
841     }
842 }
843
844 impl<CTX> HashStable<CTX> for Nonterminal
845 where
846     CTX: crate::HashStableContext,
847 {
848     fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
849         panic!("interpolated tokens should not be present in the HIR")
850     }
851 }