rustc_ast/
token.rs

1use std::borrow::Cow;
2use std::fmt;
3
4pub use LitKind::*;
5pub use NtExprKind::*;
6pub use NtPatKind::*;
7pub use TokenKind::*;
8use rustc_macros::{Decodable, Encodable, HashStable_Generic};
9use rustc_span::edition::Edition;
10use rustc_span::symbol::IdentPrintMode;
11use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym};
12#[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint.
13#[allow(hidden_glob_reexports)]
14use rustc_span::{Ident, Symbol};
15
16use crate::ast;
17use crate::util::case::Case;
18
19#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
20pub enum CommentKind {
21    Line,
22    Block,
23}
24
25// This type must not implement `Hash` due to the unusual `PartialEq` impl below.
26#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic)]
27pub enum InvisibleOrigin {
28    // From the expansion of a metavariable in a declarative macro.
29    MetaVar(MetaVarKind),
30
31    // Converted from `proc_macro::Delimiter` in
32    // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro.
33    ProcMacro,
34}
35
36impl InvisibleOrigin {
37    // Should the parser skip these invisible delimiters? Ideally this function
38    // will eventually disappear and no invisible delimiters will be skipped.
39    #[inline]
40    pub fn skip(&self) -> bool {
41        match self {
42            InvisibleOrigin::MetaVar(_) => false,
43            InvisibleOrigin::ProcMacro => true,
44        }
45    }
46}
47
48impl PartialEq for InvisibleOrigin {
49    #[inline]
50    fn eq(&self, _other: &InvisibleOrigin) -> bool {
51        // When we had AST-based nonterminals we couldn't compare them, and the
52        // old `Nonterminal` type had an `eq` that always returned false,
53        // resulting in this restriction:
54        // https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment
55        // This `eq` emulates that behaviour. We could consider lifting this
56        // restriction now but there are still cases involving invisible
57        // delimiters that make it harder than it first appears.
58        false
59    }
60}
61
62/// Annoyingly similar to `NonterminalKind`, but the slight differences are important.
63#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
64pub enum MetaVarKind {
65    Item,
66    Block,
67    Stmt,
68    Pat(NtPatKind),
69    Expr {
70        kind: NtExprKind,
71        // This field is needed for `Token::can_begin_literal_maybe_minus`.
72        can_begin_literal_maybe_minus: bool,
73        // This field is needed for `Token::can_begin_string_literal`.
74        can_begin_string_literal: bool,
75    },
76    Ty {
77        is_path: bool,
78    },
79    Ident,
80    Lifetime,
81    Literal,
82    Meta {
83        /// Will `AttrItem::meta` succeed on this, if reparsed?
84        has_meta_form: bool,
85    },
86    Path,
87    Vis,
88    TT,
89}
90
91impl fmt::Display for MetaVarKind {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        let sym = match self {
94            MetaVarKind::Item => sym::item,
95            MetaVarKind::Block => sym::block,
96            MetaVarKind::Stmt => sym::stmt,
97            MetaVarKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
98            MetaVarKind::Pat(PatParam { inferred: false }) => sym::pat_param,
99            MetaVarKind::Expr { kind: Expr2021 { inferred: true } | Expr, .. } => sym::expr,
100            MetaVarKind::Expr { kind: Expr2021 { inferred: false }, .. } => sym::expr_2021,
101            MetaVarKind::Ty { .. } => sym::ty,
102            MetaVarKind::Ident => sym::ident,
103            MetaVarKind::Lifetime => sym::lifetime,
104            MetaVarKind::Literal => sym::literal,
105            MetaVarKind::Meta { .. } => sym::meta,
106            MetaVarKind::Path => sym::path,
107            MetaVarKind::Vis => sym::vis,
108            MetaVarKind::TT => sym::tt,
109        };
110        write!(f, "{sym}")
111    }
112}
113
114/// Describes how a sequence of token trees is delimited.
115/// Cannot use `proc_macro::Delimiter` directly because this
116/// structure should implement some additional traits.
117#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
118pub enum Delimiter {
119    /// `( ... )`
120    Parenthesis,
121    /// `{ ... }`
122    Brace,
123    /// `[ ... ]`
124    Bracket,
125    /// `∅ ... ∅`
126    /// An invisible delimiter, that may, for example, appear around tokens coming from a
127    /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
128    /// `$var * 3` where `$var` is `1 + 2`.
129    /// Invisible delimiters might not survive roundtrip of a token stream through a string.
130    Invisible(InvisibleOrigin),
131}
132
133impl Delimiter {
134    // Should the parser skip these delimiters? Only happens for certain kinds
135    // of invisible delimiters. Ideally this function will eventually disappear
136    // and no invisible delimiters will be skipped.
137    #[inline]
138    pub fn skip(&self) -> bool {
139        match self {
140            Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false,
141            Delimiter::Invisible(origin) => origin.skip(),
142        }
143    }
144
145    // This exists because `InvisibleOrigin`s should be compared. It is only used for assertions.
146    pub fn eq_ignoring_invisible_origin(&self, other: &Delimiter) -> bool {
147        match (self, other) {
148            (Delimiter::Parenthesis, Delimiter::Parenthesis) => true,
149            (Delimiter::Brace, Delimiter::Brace) => true,
150            (Delimiter::Bracket, Delimiter::Bracket) => true,
151            (Delimiter::Invisible(_), Delimiter::Invisible(_)) => true,
152            _ => false,
153        }
154    }
155
156    pub fn as_open_token_kind(&self) -> TokenKind {
157        match *self {
158            Delimiter::Parenthesis => OpenParen,
159            Delimiter::Brace => OpenBrace,
160            Delimiter::Bracket => OpenBracket,
161            Delimiter::Invisible(origin) => OpenInvisible(origin),
162        }
163    }
164
165    pub fn as_close_token_kind(&self) -> TokenKind {
166        match *self {
167            Delimiter::Parenthesis => CloseParen,
168            Delimiter::Brace => CloseBrace,
169            Delimiter::Bracket => CloseBracket,
170            Delimiter::Invisible(origin) => CloseInvisible(origin),
171        }
172    }
173}
174
175// Note that the suffix is *not* considered when deciding the `LitKind` in this
176// type. This means that float literals like `1f32` are classified by this type
177// as `Int`. Only upon conversion to `ast::LitKind` will such a literal be
178// given the `Float` kind.
179#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
180pub enum LitKind {
181    Bool, // AST only, must never appear in a `Token`
182    Byte,
183    Char,
184    Integer, // e.g. `1`, `1u8`, `1f32`
185    Float,   // e.g. `1.`, `1.0`, `1e3f32`
186    Str,
187    StrRaw(u8), // raw string delimited by `n` hash symbols
188    ByteStr,
189    ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols
190    CStr,
191    CStrRaw(u8),
192    Err(ErrorGuaranteed),
193}
194
195/// A literal token.
196#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
197pub struct Lit {
198    pub kind: LitKind,
199    pub symbol: Symbol,
200    pub suffix: Option<Symbol>,
201}
202
203impl Lit {
204    pub fn new(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Lit {
205        Lit { kind, symbol, suffix }
206    }
207
208    /// Returns `true` if this is semantically a float literal. This includes
209    /// ones like `1f32` that have an `Integer` kind but a float suffix.
210    pub fn is_semantic_float(&self) -> bool {
211        match self.kind {
212            LitKind::Float => true,
213            LitKind::Integer => match self.suffix {
214                Some(sym) => sym == sym::f32 || sym == sym::f64,
215                None => false,
216            },
217            _ => false,
218        }
219    }
220
221    /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
222    /// `Parser::eat_token_lit` (excluding unary negation).
223    pub fn from_token(token: &Token) -> Option<Lit> {
224        match token.uninterpolate().kind {
225            Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)),
226            Literal(token_lit) => Some(token_lit),
227            OpenInvisible(InvisibleOrigin::MetaVar(
228                MetaVarKind::Literal | MetaVarKind::Expr { .. },
229            )) => {
230                // Unreachable with the current test suite.
231                panic!("from_token metavar");
232            }
233            _ => None,
234        }
235    }
236}
237
238impl fmt::Display for Lit {
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        let Lit { kind, symbol, suffix } = *self;
241        match kind {
242            Byte => write!(f, "b'{symbol}'")?,
243            Char => write!(f, "'{symbol}'")?,
244            Str => write!(f, "\"{symbol}\"")?,
245            StrRaw(n) => write!(
246                f,
247                "r{delim}\"{string}\"{delim}",
248                delim = "#".repeat(n as usize),
249                string = symbol
250            )?,
251            ByteStr => write!(f, "b\"{symbol}\"")?,
252            ByteStrRaw(n) => write!(
253                f,
254                "br{delim}\"{string}\"{delim}",
255                delim = "#".repeat(n as usize),
256                string = symbol
257            )?,
258            CStr => write!(f, "c\"{symbol}\"")?,
259            CStrRaw(n) => {
260                write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))?
261            }
262            Integer | Float | Bool | Err(_) => write!(f, "{symbol}")?,
263        }
264
265        if let Some(suffix) = suffix {
266            write!(f, "{suffix}")?;
267        }
268
269        Ok(())
270    }
271}
272
273impl LitKind {
274    /// An English article for the literal token kind.
275    pub fn article(self) -> &'static str {
276        match self {
277            Integer | Err(_) => "an",
278            _ => "a",
279        }
280    }
281
282    pub fn descr(self) -> &'static str {
283        match self {
284            Bool => "boolean",
285            Byte => "byte",
286            Char => "char",
287            Integer => "integer",
288            Float => "float",
289            Str | StrRaw(..) => "string",
290            ByteStr | ByteStrRaw(..) => "byte string",
291            CStr | CStrRaw(..) => "C string",
292            Err(_) => "error",
293        }
294    }
295
296    pub(crate) fn may_have_suffix(self) -> bool {
297        matches!(self, Integer | Float | Err(_))
298    }
299}
300
301pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
302    let ident_token = Token::new(Ident(name, is_raw), span);
303
304    !ident_token.is_reserved_ident()
305        || ident_token.is_path_segment_keyword()
306        || [
307            kw::Async,
308            kw::Do,
309            kw::Box,
310            kw::Break,
311            kw::Const,
312            kw::Continue,
313            kw::False,
314            kw::For,
315            kw::Gen,
316            kw::If,
317            kw::Let,
318            kw::Loop,
319            kw::Match,
320            kw::Move,
321            kw::Return,
322            kw::True,
323            kw::Try,
324            kw::Unsafe,
325            kw::While,
326            kw::Yield,
327            kw::Safe,
328            kw::Static,
329        ]
330        .contains(&name)
331}
332
333fn ident_can_begin_type(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
334    let ident_token = Token::new(Ident(name, is_raw), span);
335
336    !ident_token.is_reserved_ident()
337        || ident_token.is_path_segment_keyword()
338        || [kw::Underscore, kw::For, kw::Impl, kw::Fn, kw::Unsafe, kw::Extern, kw::Typeof, kw::Dyn]
339            .contains(&name)
340}
341
342#[derive(PartialEq, Encodable, Decodable, Debug, Copy, Clone, HashStable_Generic)]
343pub enum IdentIsRaw {
344    No,
345    Yes,
346}
347
348impl IdentIsRaw {
349    pub fn to_print_mode_ident(self) -> IdentPrintMode {
350        match self {
351            IdentIsRaw::No => IdentPrintMode::Normal,
352            IdentIsRaw::Yes => IdentPrintMode::RawIdent,
353        }
354    }
355    pub fn to_print_mode_lifetime(self) -> IdentPrintMode {
356        match self {
357            IdentIsRaw::No => IdentPrintMode::Normal,
358            IdentIsRaw::Yes => IdentPrintMode::RawLifetime,
359        }
360    }
361}
362
363impl From<bool> for IdentIsRaw {
364    fn from(b: bool) -> Self {
365        if b { Self::Yes } else { Self::No }
366    }
367}
368
369#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
370pub enum TokenKind {
371    /* Expression-operator symbols. */
372    /// `=`
373    Eq,
374    /// `<`
375    Lt,
376    /// `<=`
377    Le,
378    /// `==`
379    EqEq,
380    /// `!=`
381    Ne,
382    /// `>=`
383    Ge,
384    /// `>`
385    Gt,
386    /// `&&`
387    AndAnd,
388    /// `||`
389    OrOr,
390    /// `!`
391    Bang,
392    /// `~`
393    Tilde,
394    // `+`
395    Plus,
396    // `-`
397    Minus,
398    // `*`
399    Star,
400    // `/`
401    Slash,
402    // `%`
403    Percent,
404    // `^`
405    Caret,
406    // `&`
407    And,
408    // `|`
409    Or,
410    // `<<`
411    Shl,
412    // `>>`
413    Shr,
414    // `+=`
415    PlusEq,
416    // `-=`
417    MinusEq,
418    // `*=`
419    StarEq,
420    // `/=`
421    SlashEq,
422    // `%=`
423    PercentEq,
424    // `^=`
425    CaretEq,
426    // `&=`
427    AndEq,
428    // `|=`
429    OrEq,
430    // `<<=`
431    ShlEq,
432    // `>>=`
433    ShrEq,
434
435    /* Structural symbols */
436    /// `@`
437    At,
438    /// `.`
439    Dot,
440    /// `..`
441    DotDot,
442    /// `...`
443    DotDotDot,
444    /// `..=`
445    DotDotEq,
446    /// `,`
447    Comma,
448    /// `;`
449    Semi,
450    /// `:`
451    Colon,
452    /// `::`
453    PathSep,
454    /// `->`
455    RArrow,
456    /// `<-`
457    LArrow,
458    /// `=>`
459    FatArrow,
460    /// `#`
461    Pound,
462    /// `$`
463    Dollar,
464    /// `?`
465    Question,
466    /// Used by proc macros for representing lifetimes, not generated by lexer right now.
467    SingleQuote,
468    /// `(`
469    OpenParen,
470    /// `)`
471    CloseParen,
472    /// `{`
473    OpenBrace,
474    /// `}`
475    CloseBrace,
476    /// `[`
477    OpenBracket,
478    /// `]`
479    CloseBracket,
480    /// Invisible opening delimiter, produced by a macro.
481    OpenInvisible(InvisibleOrigin),
482    /// Invisible closing delimiter, produced by a macro.
483    CloseInvisible(InvisibleOrigin),
484
485    /* Literals */
486    Literal(Lit),
487
488    /// Identifier token.
489    /// Do not forget about `NtIdent` when you want to match on identifiers.
490    /// It's recommended to use `Token::{ident,uninterpolate}` and
491    /// `Parser::token_uninterpolated_span` to treat regular and interpolated
492    /// identifiers in the same way.
493    Ident(Symbol, IdentIsRaw),
494    /// This identifier (and its span) is the identifier passed to the
495    /// declarative macro. The span in the surrounding `Token` is the span of
496    /// the `ident` metavariable in the macro's RHS.
497    NtIdent(Ident, IdentIsRaw),
498
499    /// Lifetime identifier token.
500    /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
501    /// It's recommended to use `Token::{ident,uninterpolate}` and
502    /// `Parser::token_uninterpolated_span` to treat regular and interpolated
503    /// identifiers in the same way.
504    Lifetime(Symbol, IdentIsRaw),
505    /// This identifier (and its span) is the lifetime passed to the
506    /// declarative macro. The span in the surrounding `Token` is the span of
507    /// the `lifetime` metavariable in the macro's RHS.
508    NtLifetime(Ident, IdentIsRaw),
509
510    /// A doc comment token.
511    /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
512    /// similarly to symbols in string literal tokens.
513    DocComment(CommentKind, ast::AttrStyle, Symbol),
514
515    /// End Of File
516    Eof,
517}
518
519#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
520pub struct Token {
521    pub kind: TokenKind,
522    pub span: Span,
523}
524
525impl TokenKind {
526    pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option<Symbol>) -> TokenKind {
527        Literal(Lit::new(kind, symbol, suffix))
528    }
529
530    /// An approximation to proc-macro-style single-character operators used by
531    /// rustc parser. If the operator token can be broken into two tokens, the
532    /// first of which has `n` (1 or 2) chars, then this function performs that
533    /// operation, otherwise it returns `None`.
534    pub fn break_two_token_op(&self, n: u32) -> Option<(TokenKind, TokenKind)> {
535        assert!(n == 1 || n == 2);
536        Some(match (self, n) {
537            (Le, 1) => (Lt, Eq),
538            (EqEq, 1) => (Eq, Eq),
539            (Ne, 1) => (Bang, Eq),
540            (Ge, 1) => (Gt, Eq),
541            (AndAnd, 1) => (And, And),
542            (OrOr, 1) => (Or, Or),
543            (Shl, 1) => (Lt, Lt),
544            (Shr, 1) => (Gt, Gt),
545            (PlusEq, 1) => (Plus, Eq),
546            (MinusEq, 1) => (Minus, Eq),
547            (StarEq, 1) => (Star, Eq),
548            (SlashEq, 1) => (Slash, Eq),
549            (PercentEq, 1) => (Percent, Eq),
550            (CaretEq, 1) => (Caret, Eq),
551            (AndEq, 1) => (And, Eq),
552            (OrEq, 1) => (Or, Eq),
553            (ShlEq, 1) => (Lt, Le),  // `<` + `<=`
554            (ShlEq, 2) => (Shl, Eq), // `<<` + `=`
555            (ShrEq, 1) => (Gt, Ge),  // `>` + `>=`
556            (ShrEq, 2) => (Shr, Eq), // `>>` + `=`
557            (DotDot, 1) => (Dot, Dot),
558            (DotDotDot, 1) => (Dot, DotDot), // `.` + `..`
559            (DotDotDot, 2) => (DotDot, Dot), // `..` + `.`
560            (DotDotEq, 2) => (DotDot, Eq),
561            (PathSep, 1) => (Colon, Colon),
562            (RArrow, 1) => (Minus, Gt),
563            (LArrow, 1) => (Lt, Minus),
564            (FatArrow, 1) => (Eq, Gt),
565            _ => return None,
566        })
567    }
568
569    /// Returns tokens that are likely to be typed accidentally instead of the current token.
570    /// Enables better error recovery when the wrong token is found.
571    pub fn similar_tokens(&self) -> &[TokenKind] {
572        match self {
573            Comma => &[Dot, Lt, Semi],
574            Semi => &[Colon, Comma],
575            Colon => &[Semi],
576            FatArrow => &[Eq, RArrow, Ge, Gt],
577            _ => &[],
578        }
579    }
580
581    pub fn should_end_const_arg(&self) -> bool {
582        matches!(self, Gt | Ge | Shr | ShrEq)
583    }
584
585    pub fn is_delim(&self) -> bool {
586        self.open_delim().is_some() || self.close_delim().is_some()
587    }
588
589    pub fn open_delim(&self) -> Option<Delimiter> {
590        match *self {
591            OpenParen => Some(Delimiter::Parenthesis),
592            OpenBrace => Some(Delimiter::Brace),
593            OpenBracket => Some(Delimiter::Bracket),
594            OpenInvisible(origin) => Some(Delimiter::Invisible(origin)),
595            _ => None,
596        }
597    }
598
599    pub fn close_delim(&self) -> Option<Delimiter> {
600        match *self {
601            CloseParen => Some(Delimiter::Parenthesis),
602            CloseBrace => Some(Delimiter::Brace),
603            CloseBracket => Some(Delimiter::Bracket),
604            CloseInvisible(origin) => Some(Delimiter::Invisible(origin)),
605            _ => None,
606        }
607    }
608
609    pub fn is_close_delim_or_eof(&self) -> bool {
610        match self {
611            CloseParen | CloseBrace | CloseBracket | CloseInvisible(_) | Eof => true,
612            _ => false,
613        }
614    }
615}
616
617impl Token {
618    pub fn new(kind: TokenKind, span: Span) -> Self {
619        Token { kind, span }
620    }
621
622    /// Some token that will be thrown away later.
623    pub fn dummy() -> Self {
624        Token::new(TokenKind::Question, DUMMY_SP)
625    }
626
627    /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary.
628    pub fn from_ast_ident(ident: Ident) -> Self {
629        Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span)
630    }
631
632    pub fn is_range_separator(&self) -> bool {
633        [DotDot, DotDotDot, DotDotEq].contains(&self.kind)
634    }
635
636    pub fn is_punct(&self) -> bool {
637        match self.kind {
638            Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Bang | Tilde | Plus | Minus
639            | Star | Slash | Percent | Caret | And | Or | Shl | Shr | PlusEq | MinusEq | StarEq
640            | SlashEq | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | Dot | DotDot
641            | DotDotDot | DotDotEq | Comma | Semi | Colon | PathSep | RArrow | LArrow
642            | FatArrow | Pound | Dollar | Question | SingleQuote => true,
643
644            OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
645            | OpenInvisible(_) | CloseInvisible(_) | Literal(..) | DocComment(..) | Ident(..)
646            | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false,
647        }
648    }
649
650    pub fn is_like_plus(&self) -> bool {
651        matches!(self.kind, Plus | PlusEq)
652    }
653
654    /// Returns `true` if the token can appear at the start of an expression.
655    ///
656    /// **NB**: Take care when modifying this function, since it will change
657    /// the stable set of tokens that are allowed to match an expr nonterminal.
658    pub fn can_begin_expr(&self) -> bool {
659        match self.uninterpolate().kind {
660            Ident(name, is_raw)              =>
661                ident_can_begin_expr(name, self.span, is_raw), // value name or keyword
662            OpenParen                         | // tuple
663            OpenBrace                         | // block
664            OpenBracket                       | // array
665            Literal(..)                       | // literal
666            Bang                              | // operator not
667            Minus                             | // unary minus
668            Star                              | // dereference
669            Or | OrOr                         | // closure
670            And                               | // reference
671            AndAnd                            | // double reference
672            // DotDotDot is no longer supported, but we need some way to display the error
673            DotDot | DotDotDot | DotDotEq     | // range notation
674            Lt | Shl                          | // associated path
675            PathSep                           | // global path
676            Lifetime(..)                      | // labeled loop
677            Pound                             => true, // expression attributes
678            OpenInvisible(InvisibleOrigin::MetaVar(
679                MetaVarKind::Block |
680                MetaVarKind::Expr { .. } |
681                MetaVarKind::Literal |
682                MetaVarKind::Path
683            )) => true,
684            _ => false,
685        }
686    }
687
688    /// Returns `true` if the token can appear at the start of a pattern.
689    ///
690    /// Shamelessly borrowed from `can_begin_expr`, only used for diagnostics right now.
691    pub fn can_begin_pattern(&self, pat_kind: NtPatKind) -> bool {
692        match &self.uninterpolate().kind {
693            // box, ref, mut, and other identifiers (can stricten)
694            Ident(..) | NtIdent(..) |
695            OpenParen |                          // tuple pattern
696            OpenBracket |                        // slice pattern
697            And |                                // reference
698            Minus |                              // negative literal
699            AndAnd |                             // double reference
700            Literal(_) |                         // literal
701            DotDot |                             // range pattern (future compat)
702            DotDotDot |                          // range pattern (future compat)
703            PathSep |                            // path
704            Lt |                                 // path (UFCS constant)
705            Shl => true,                         // path (double UFCS)
706            Or => matches!(pat_kind, PatWithOr), // leading vert `|` or-pattern
707            OpenInvisible(InvisibleOrigin::MetaVar(
708                MetaVarKind::Expr { .. } |
709                MetaVarKind::Literal |
710                MetaVarKind::Meta { .. } |
711                MetaVarKind::Pat(_) |
712                MetaVarKind::Path |
713                MetaVarKind::Ty { .. }
714            )) => true,
715            _ => false,
716        }
717    }
718
719    /// Returns `true` if the token can appear at the start of a type.
720    pub fn can_begin_type(&self) -> bool {
721        match self.uninterpolate().kind {
722            Ident(name, is_raw) =>
723                ident_can_begin_type(name, self.span, is_raw), // type name or keyword
724            OpenParen                         | // tuple
725            OpenBracket                       | // array
726            Bang                              | // never
727            Star                              | // raw pointer
728            And                               | // reference
729            AndAnd                            | // double reference
730            Question                          | // maybe bound in trait object
731            Lifetime(..)                      | // lifetime bound in trait object
732            Lt | Shl                          | // associated path
733            PathSep => true,                    // global path
734            OpenInvisible(InvisibleOrigin::MetaVar(
735                MetaVarKind::Ty { .. } |
736                MetaVarKind::Path
737            )) => true,
738            // For anonymous structs or unions, which only appear in specific positions
739            // (type of struct fields or union fields), we don't consider them as regular types
740            _ => false,
741        }
742    }
743
744    /// Returns `true` if the token can appear at the start of a const param.
745    pub fn can_begin_const_arg(&self) -> bool {
746        match self.kind {
747            OpenBrace | Literal(..) | Minus => true,
748            Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
749            OpenInvisible(InvisibleOrigin::MetaVar(
750                MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal,
751            )) => true,
752            _ => false,
753        }
754    }
755
756    /// Returns `true` if the token can appear at the start of an item.
757    pub fn can_begin_item(&self) -> bool {
758        match self.kind {
759            Ident(name, _) => [
760                kw::Fn,
761                kw::Use,
762                kw::Struct,
763                kw::Enum,
764                kw::Pub,
765                kw::Trait,
766                kw::Extern,
767                kw::Impl,
768                kw::Unsafe,
769                kw::Const,
770                kw::Safe,
771                kw::Static,
772                kw::Union,
773                kw::Macro,
774                kw::Mod,
775                kw::Type,
776            ]
777            .contains(&name),
778            _ => false,
779        }
780    }
781
782    /// Returns `true` if the token is any literal.
783    pub fn is_lit(&self) -> bool {
784        matches!(self.kind, Literal(..))
785    }
786
787    /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
788    /// for example a '-42', or one of the boolean idents).
789    ///
790    /// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
791    ///
792    /// Keep this in sync with `Lit::from_token` and `Parser::eat_token_lit`
793    /// (excluding unary negation).
794    pub fn can_begin_literal_maybe_minus(&self) -> bool {
795        match self.uninterpolate().kind {
796            Literal(..) | Minus => true,
797            Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true,
798            OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind {
799                MetaVarKind::Literal => true,
800                MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => {
801                    can_begin_literal_maybe_minus
802                }
803                _ => false,
804            },
805            _ => false,
806        }
807    }
808
809    pub fn can_begin_string_literal(&self) -> bool {
810        match self.uninterpolate().kind {
811            Literal(..) => true,
812            OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind {
813                MetaVarKind::Literal => true,
814                MetaVarKind::Expr { can_begin_string_literal, .. } => can_begin_string_literal,
815                _ => false,
816            },
817            _ => false,
818        }
819    }
820
821    /// A convenience function for matching on identifiers during parsing.
822    /// Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token
823    /// into the regular identifier or lifetime token it refers to,
824    /// otherwise returns the original token.
825    pub fn uninterpolate(&self) -> Cow<'_, Token> {
826        match self.kind {
827            NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)),
828            NtLifetime(ident, is_raw) => {
829                Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span))
830            }
831            _ => Cow::Borrowed(self),
832        }
833    }
834
835    /// Returns an identifier if this token is an identifier.
836    #[inline]
837    pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> {
838        // We avoid using `Token::uninterpolate` here because it's slow.
839        match self.kind {
840            Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
841            NtIdent(ident, is_raw) => Some((ident, is_raw)),
842            _ => None,
843        }
844    }
845
846    /// Returns a lifetime identifier if this token is a lifetime.
847    #[inline]
848    pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> {
849        // We avoid using `Token::uninterpolate` here because it's slow.
850        match self.kind {
851            Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
852            NtLifetime(ident, is_raw) => Some((ident, is_raw)),
853            _ => None,
854        }
855    }
856
857    /// Returns `true` if the token is an identifier.
858    pub fn is_ident(&self) -> bool {
859        self.ident().is_some()
860    }
861
862    /// Returns `true` if the token is a lifetime.
863    pub fn is_lifetime(&self) -> bool {
864        self.lifetime().is_some()
865    }
866
867    /// Returns `true` if the token is an identifier whose name is the given
868    /// string slice.
869    pub fn is_ident_named(&self, name: Symbol) -> bool {
870        self.ident().is_some_and(|(ident, _)| ident.name == name)
871    }
872
873    /// Is this a pre-parsed expression dropped into the token stream
874    /// (which happens while parsing the result of macro expansion)?
875    pub fn is_metavar_expr(&self) -> bool {
876        matches!(
877            self.is_metavar_seq(),
878            Some(
879                MetaVarKind::Expr { .. }
880                    | MetaVarKind::Literal
881                    | MetaVarKind::Path
882                    | MetaVarKind::Block
883            )
884        )
885    }
886
887    /// Are we at a block from a metavar (`$b:block`)?
888    pub fn is_metavar_block(&self) -> bool {
889        matches!(self.is_metavar_seq(), Some(MetaVarKind::Block))
890    }
891
892    /// Returns `true` if the token is either the `mut` or `const` keyword.
893    pub fn is_mutability(&self) -> bool {
894        self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)
895    }
896
897    pub fn is_qpath_start(&self) -> bool {
898        self == &Lt || self == &Shl
899    }
900
901    pub fn is_path_start(&self) -> bool {
902        self == &PathSep
903            || self.is_qpath_start()
904            || matches!(self.is_metavar_seq(), Some(MetaVarKind::Path))
905            || self.is_path_segment_keyword()
906            || self.is_non_reserved_ident()
907    }
908
909    /// Returns `true` if the token is a given keyword, `kw`.
910    pub fn is_keyword(&self, kw: Symbol) -> bool {
911        self.is_non_raw_ident_where(|id| id.name == kw)
912    }
913
914    /// Returns `true` if the token is a given keyword, `kw` or if `case` is `Insensitive` and this
915    /// token is an identifier equal to `kw` ignoring the case.
916    pub fn is_keyword_case(&self, kw: Symbol, case: Case) -> bool {
917        self.is_keyword(kw)
918            || (case == Case::Insensitive
919                && self.is_non_raw_ident_where(|id| {
920                    // Do an ASCII case-insensitive match, because all keywords are ASCII.
921                    id.name.as_str().eq_ignore_ascii_case(kw.as_str())
922                }))
923    }
924
925    pub fn is_path_segment_keyword(&self) -> bool {
926        self.is_non_raw_ident_where(Ident::is_path_segment_keyword)
927    }
928
929    /// Returns true for reserved identifiers used internally for elided lifetimes,
930    /// unnamed method parameters, crate root module, error recovery etc.
931    pub fn is_special_ident(&self) -> bool {
932        self.is_non_raw_ident_where(Ident::is_special)
933    }
934
935    /// Returns `true` if the token is a keyword used in the language.
936    pub fn is_used_keyword(&self) -> bool {
937        self.is_non_raw_ident_where(Ident::is_used_keyword)
938    }
939
940    /// Returns `true` if the token is a keyword reserved for possible future use.
941    pub fn is_unused_keyword(&self) -> bool {
942        self.is_non_raw_ident_where(Ident::is_unused_keyword)
943    }
944
945    /// Returns `true` if the token is either a special identifier or a keyword.
946    pub fn is_reserved_ident(&self) -> bool {
947        self.is_non_raw_ident_where(Ident::is_reserved)
948    }
949
950    pub fn is_non_reserved_ident(&self) -> bool {
951        self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !Ident::is_reserved(id))
952    }
953
954    /// Returns `true` if the token is the identifier `true` or `false`.
955    pub fn is_bool_lit(&self) -> bool {
956        self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
957    }
958
959    pub fn is_numeric_lit(&self) -> bool {
960        matches!(
961            self.kind,
962            Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
963        )
964    }
965
966    /// Returns `true` if the token is the integer literal.
967    pub fn is_integer_lit(&self) -> bool {
968        matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. }))
969    }
970
971    /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
972    pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
973        match self.ident() {
974            Some((id, IdentIsRaw::No)) => pred(id),
975            _ => false,
976        }
977    }
978
979    /// Is this an invisible open delimiter at the start of a token sequence
980    /// from an expanded metavar?
981    pub fn is_metavar_seq(&self) -> Option<MetaVarKind> {
982        match self.kind {
983            OpenInvisible(InvisibleOrigin::MetaVar(kind)) => Some(kind),
984            _ => None,
985        }
986    }
987
988    pub fn glue(&self, joint: &Token) -> Option<Token> {
989        let kind = match (&self.kind, &joint.kind) {
990            (Eq, Eq) => EqEq,
991            (Eq, Gt) => FatArrow,
992            (Eq, _) => return None,
993
994            (Lt, Eq) => Le,
995            (Lt, Lt) => Shl,
996            (Lt, Le) => ShlEq,
997            (Lt, Minus) => LArrow,
998            (Lt, _) => return None,
999
1000            (Gt, Eq) => Ge,
1001            (Gt, Gt) => Shr,
1002            (Gt, Ge) => ShrEq,
1003            (Gt, _) => return None,
1004
1005            (Bang, Eq) => Ne,
1006            (Bang, _) => return None,
1007
1008            (Plus, Eq) => PlusEq,
1009            (Plus, _) => return None,
1010
1011            (Minus, Eq) => MinusEq,
1012            (Minus, Gt) => RArrow,
1013            (Minus, _) => return None,
1014
1015            (Star, Eq) => StarEq,
1016            (Star, _) => return None,
1017
1018            (Slash, Eq) => SlashEq,
1019            (Slash, _) => return None,
1020
1021            (Percent, Eq) => PercentEq,
1022            (Percent, _) => return None,
1023
1024            (Caret, Eq) => CaretEq,
1025            (Caret, _) => return None,
1026
1027            (And, Eq) => AndEq,
1028            (And, And) => AndAnd,
1029            (And, _) => return None,
1030
1031            (Or, Eq) => OrEq,
1032            (Or, Or) => OrOr,
1033            (Or, _) => return None,
1034
1035            (Shl, Eq) => ShlEq,
1036            (Shl, _) => return None,
1037
1038            (Shr, Eq) => ShrEq,
1039            (Shr, _) => return None,
1040
1041            (Dot, Dot) => DotDot,
1042            (Dot, DotDot) => DotDotDot,
1043            (Dot, _) => return None,
1044
1045            (DotDot, Dot) => DotDotDot,
1046            (DotDot, Eq) => DotDotEq,
1047            (DotDot, _) => return None,
1048
1049            (Colon, Colon) => PathSep,
1050            (Colon, _) => return None,
1051
1052            (SingleQuote, Ident(name, is_raw)) => {
1053                Lifetime(Symbol::intern(&format!("'{name}")), *is_raw)
1054            }
1055            (SingleQuote, _) => return None,
1056
1057            (
1058                Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | PlusEq | MinusEq | StarEq | SlashEq
1059                | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | DotDotDot | DotDotEq
1060                | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question
1061                | OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
1062                | OpenInvisible(_) | CloseInvisible(_) | Literal(..) | Ident(..) | NtIdent(..)
1063                | Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof,
1064                _,
1065            ) => {
1066                return None;
1067            }
1068        };
1069
1070        Some(Token::new(kind, self.span.to(joint.span)))
1071    }
1072}
1073
1074impl PartialEq<TokenKind> for Token {
1075    #[inline]
1076    fn eq(&self, rhs: &TokenKind) -> bool {
1077        self.kind == *rhs
1078    }
1079}
1080
1081#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1082pub enum NtPatKind {
1083    // Matches or-patterns. Was written using `pat` in edition 2021 or later.
1084    PatWithOr,
1085    // Doesn't match or-patterns.
1086    // - `inferred`: was written using `pat` in edition 2015 or 2018.
1087    // - `!inferred`: was written using `pat_param`.
1088    PatParam { inferred: bool },
1089}
1090
1091#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1092pub enum NtExprKind {
1093    // Matches expressions using the post-edition 2024. Was written using
1094    // `expr` in edition 2024 or later.
1095    Expr,
1096    // Matches expressions using the pre-edition 2024 rules.
1097    // - `inferred`: was written using `expr` in edition 2021 or earlier.
1098    // - `!inferred`: was written using `expr_2021`.
1099    Expr2021 { inferred: bool },
1100}
1101
1102/// A macro nonterminal, known in documentation as a fragment specifier.
1103#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
1104pub enum NonterminalKind {
1105    Item,
1106    Block,
1107    Stmt,
1108    Pat(NtPatKind),
1109    Expr(NtExprKind),
1110    Ty,
1111    Ident,
1112    Lifetime,
1113    Literal,
1114    Meta,
1115    Path,
1116    Vis,
1117    TT,
1118}
1119
1120impl NonterminalKind {
1121    /// The `edition` closure is used to get the edition for the given symbol. Doing
1122    /// `span.edition()` is expensive, so we do it lazily.
1123    pub fn from_symbol(
1124        symbol: Symbol,
1125        edition: impl FnOnce() -> Edition,
1126    ) -> Option<NonterminalKind> {
1127        Some(match symbol {
1128            sym::item => NonterminalKind::Item,
1129            sym::block => NonterminalKind::Block,
1130            sym::stmt => NonterminalKind::Stmt,
1131            sym::pat => {
1132                if edition().at_least_rust_2021() {
1133                    NonterminalKind::Pat(PatWithOr)
1134                } else {
1135                    NonterminalKind::Pat(PatParam { inferred: true })
1136                }
1137            }
1138            sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
1139            sym::expr => {
1140                if edition().at_least_rust_2024() {
1141                    NonterminalKind::Expr(Expr)
1142                } else {
1143                    NonterminalKind::Expr(Expr2021 { inferred: true })
1144                }
1145            }
1146            sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
1147            sym::ty => NonterminalKind::Ty,
1148            sym::ident => NonterminalKind::Ident,
1149            sym::lifetime => NonterminalKind::Lifetime,
1150            sym::literal => NonterminalKind::Literal,
1151            sym::meta => NonterminalKind::Meta,
1152            sym::path => NonterminalKind::Path,
1153            sym::vis => NonterminalKind::Vis,
1154            sym::tt => NonterminalKind::TT,
1155            _ => return None,
1156        })
1157    }
1158
1159    fn symbol(self) -> Symbol {
1160        match self {
1161            NonterminalKind::Item => sym::item,
1162            NonterminalKind::Block => sym::block,
1163            NonterminalKind::Stmt => sym::stmt,
1164            NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
1165            NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
1166            NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
1167            NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
1168            NonterminalKind::Ty => sym::ty,
1169            NonterminalKind::Ident => sym::ident,
1170            NonterminalKind::Lifetime => sym::lifetime,
1171            NonterminalKind::Literal => sym::literal,
1172            NonterminalKind::Meta => sym::meta,
1173            NonterminalKind::Path => sym::path,
1174            NonterminalKind::Vis => sym::vis,
1175            NonterminalKind::TT => sym::tt,
1176        }
1177    }
1178}
1179
1180impl fmt::Display for NonterminalKind {
1181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1182        write!(f, "{}", self.symbol())
1183    }
1184}
1185
1186// Some types are used a lot. Make sure they don't unintentionally get bigger.
1187#[cfg(target_pointer_width = "64")]
1188mod size_asserts {
1189    use rustc_data_structures::static_assert_size;
1190
1191    use super::*;
1192    // tidy-alphabetical-start
1193    static_assert_size!(Lit, 12);
1194    static_assert_size!(LitKind, 2);
1195    static_assert_size!(Token, 24);
1196    static_assert_size!(TokenKind, 16);
1197    // tidy-alphabetical-end
1198}