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