about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_parse/src/parser/mod.rs')
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs397
1 files changed, 196 insertions, 201 deletions
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 0d220e74c0e..2637ea268c8 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -8,6 +8,7 @@ mod nonterminal;
 mod pat;
 mod path;
 mod stmt;
+pub mod token_type;
 mod ty;
 
 use std::assert_matches::debug_assert_matches;
@@ -24,9 +25,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::token::{
     self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, Token, TokenKind,
 };
-use rustc_ast::tokenstream::{
-    AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor,
-};
+use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
     self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID,
@@ -41,11 +40,14 @@ use rustc_index::interval::IntervalSet;
 use rustc_session::parse::ParseSess;
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
 use thin_vec::ThinVec;
+use token_type::TokenTypeSet;
+pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType};
 use tracing::debug;
 
 use crate::errors::{
     self, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral,
 };
+use crate::exp;
 use crate::lexer::UnmatchedDelim;
 
 #[cfg(test)]
@@ -143,7 +145,7 @@ pub struct Parser<'a> {
     pub prev_token: Token,
     pub capture_cfg: bool,
     restrictions: Restrictions,
-    expected_tokens: Vec<TokenType>,
+    expected_token_types: TokenTypeSet,
     token_cursor: TokenCursor,
     // The number of calls to `bump`, i.e. the position in the token stream.
     num_bump_calls: u32,
@@ -186,9 +188,9 @@ pub struct Parser<'a> {
     recovery: Recovery,
 }
 
-// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
-// it doesn't unintentionally get bigger.
-#[cfg(target_pointer_width = "64")]
+// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with
+// nonterminals. Make sure it doesn't unintentionally get bigger.
+#[cfg(all(target_pointer_width = "64", not(target_arch = "s390x")))]
 rustc_data_structures::static_assert_size!(Parser<'_>, 288);
 
 /// Stores span information about a closure.
@@ -272,21 +274,48 @@ struct CaptureState {
     seen_attrs: IntervalSet<AttrId>,
 }
 
-/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
+#[derive(Clone, Debug)]
+struct TokenTreeCursor {
+    stream: TokenStream,
+    /// Points to the current token tree in the stream. In `TokenCursor::curr`,
+    /// this can be any token tree. In `TokenCursor::stack`, this is always a
+    /// `TokenTree::Delimited`.
+    index: usize,
+}
+
+impl TokenTreeCursor {
+    #[inline]
+    fn new(stream: TokenStream) -> Self {
+        TokenTreeCursor { stream, index: 0 }
+    }
+
+    #[inline]
+    fn curr(&self) -> Option<&TokenTree> {
+        self.stream.get(self.index)
+    }
+
+    #[inline]
+    fn bump(&mut self) {
+        self.index += 1;
+    }
+}
+
+/// A `TokenStream` cursor that produces `Token`s. It's a bit odd that
 /// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b)
 /// use this type to emit them as a linear sequence. But a linear sequence is
 /// what the parser expects, for the most part.
 #[derive(Clone, Debug)]
 struct TokenCursor {
-    // Cursor for the current (innermost) token stream. The delimiters for this
-    // token stream are found in `self.stack.last()`; when that is `None` then
-    // we are in the outermost token stream which never has delimiters.
-    tree_cursor: TokenTreeCursor,
-
-    // Token streams surrounding the current one. The delimiters for stack[n]'s
-    // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters
-    // because it's the outermost token stream which never has delimiters.
-    stack: Vec<(TokenTreeCursor, DelimSpan, DelimSpacing, Delimiter)>,
+    // Cursor for the current (innermost) token stream. The index within the
+    // cursor can point to any token tree in the stream (or one past the end).
+    // The delimiters for this token stream are found in `self.stack.last()`;
+    // if that is `None` we are in the outermost token stream which never has
+    // delimiters.
+    curr: TokenTreeCursor,
+
+    // Token streams surrounding the current one. The index within each cursor
+    // always points to a `TokenTree::Delimited`.
+    stack: Vec<TokenTreeCursor>,
 }
 
 impl TokenCursor {
@@ -301,32 +330,33 @@ impl TokenCursor {
             // FIXME: we currently don't return `Delimiter::Invisible` open/close delims. To fix
             // #67062 we will need to, whereupon the `delim != Delimiter::Invisible` conditions
             // below can be removed.
-            if let Some(tree) = self.tree_cursor.next_ref() {
+            if let Some(tree) = self.curr.curr() {
                 match tree {
                     &TokenTree::Token(ref token, spacing) => {
                         debug_assert!(!matches!(
                             token.kind,
                             token::OpenDelim(_) | token::CloseDelim(_)
                         ));
-                        return (token.clone(), spacing);
+                        let res = (token.clone(), spacing);
+                        self.curr.bump();
+                        return res;
                     }
                     &TokenTree::Delimited(sp, spacing, delim, ref tts) => {
-                        let trees = tts.clone().into_trees();
-                        self.stack.push((
-                            mem::replace(&mut self.tree_cursor, trees),
-                            sp,
-                            spacing,
-                            delim,
-                        ));
+                        let trees = TokenTreeCursor::new(tts.clone());
+                        self.stack.push(mem::replace(&mut self.curr, trees));
                         if !delim.skip() {
                             return (Token::new(token::OpenDelim(delim), sp.open), spacing.open);
                         }
                         // No open delimiter to return; continue on to the next iteration.
                     }
                 };
-            } else if let Some((tree_cursor, span, spacing, delim)) = self.stack.pop() {
+            } else if let Some(parent) = self.stack.pop() {
                 // We have exhausted this token stream. Move back to its parent token stream.
-                self.tree_cursor = tree_cursor;
+                let Some(&TokenTree::Delimited(span, spacing, delim, _)) = parent.curr() else {
+                    panic!("parent should be Delimited")
+                };
+                self.curr = parent;
+                self.curr.bump(); // move past the `Delimited`
                 if !delim.skip() {
                     return (Token::new(token::CloseDelim(delim), span.close), spacing.close);
                 }
@@ -341,48 +371,21 @@ impl TokenCursor {
     }
 }
 
-#[derive(Debug, Clone, PartialEq)]
-enum TokenType {
-    Token(TokenKind),
-    Keyword(Symbol),
-    Operator,
-    Lifetime,
-    Ident,
-    Path,
-    Type,
-    Const,
-}
-
-impl TokenType {
-    fn to_string(&self) -> String {
-        match self {
-            TokenType::Token(t) => format!("`{}`", pprust::token_kind_to_string(t)),
-            TokenType::Keyword(kw) => format!("`{kw}`"),
-            TokenType::Operator => "an operator".to_string(),
-            TokenType::Lifetime => "lifetime".to_string(),
-            TokenType::Ident => "identifier".to_string(),
-            TokenType::Path => "path".to_string(),
-            TokenType::Type => "type".to_string(),
-            TokenType::Const => "a const expression".to_string(),
-        }
-    }
-}
-
 /// A sequence separator.
 #[derive(Debug)]
-struct SeqSep {
+struct SeqSep<'a> {
     /// The separator token.
-    sep: Option<TokenKind>,
+    sep: Option<ExpTokenPair<'a>>,
     /// `true` if a trailing separator is allowed.
     trailing_sep_allowed: bool,
 }
 
-impl SeqSep {
-    fn trailing_allowed(t: TokenKind) -> SeqSep {
-        SeqSep { sep: Some(t), trailing_sep_allowed: true }
+impl<'a> SeqSep<'a> {
+    fn trailing_allowed(sep: ExpTokenPair<'a>) -> SeqSep<'a> {
+        SeqSep { sep: Some(sep), trailing_sep_allowed: true }
     }
 
-    fn none() -> SeqSep {
+    fn none() -> SeqSep<'a> {
         SeqSep { sep: None, trailing_sep_allowed: false }
     }
 }
@@ -464,8 +467,8 @@ impl<'a> Parser<'a> {
             prev_token: Token::dummy(),
             capture_cfg: false,
             restrictions: Restrictions::empty(),
-            expected_tokens: Vec::new(),
-            token_cursor: TokenCursor { tree_cursor: stream.into_trees(), stack: Vec::new() },
+            expected_token_types: TokenTypeSet::new(),
+            token_cursor: TokenCursor { curr: TokenTreeCursor::new(stream), stack: Vec::new() },
             num_bump_calls: 0,
             break_last_token: 0,
             unmatched_angle_bracket_count: 0,
@@ -527,16 +530,16 @@ impl<'a> Parser<'a> {
     }
 
     /// Expects and consumes the token `t`. Signals an error if the next token is not `t`.
-    pub fn expect(&mut self, t: &TokenKind) -> PResult<'a, Recovered> {
-        if self.expected_tokens.is_empty() {
-            if self.token == *t {
+    pub fn expect(&mut self, exp: ExpTokenPair<'_>) -> PResult<'a, Recovered> {
+        if self.expected_token_types.is_empty() {
+            if self.token == *exp.tok {
                 self.bump();
                 Ok(Recovered::No)
             } else {
-                self.unexpected_try_recover(t)
+                self.unexpected_try_recover(exp.tok)
             }
         } else {
-            self.expect_one_of(slice::from_ref(t), &[])
+            self.expect_one_of(slice::from_ref(&exp), &[])
         }
     }
 
@@ -545,13 +548,13 @@ impl<'a> Parser<'a> {
     /// anything. Signal a fatal error if next token is unexpected.
     fn expect_one_of(
         &mut self,
-        edible: &[TokenKind],
-        inedible: &[TokenKind],
+        edible: &[ExpTokenPair<'_>],
+        inedible: &[ExpTokenPair<'_>],
     ) -> PResult<'a, Recovered> {
-        if edible.contains(&self.token.kind) {
+        if edible.iter().any(|exp| exp.tok == &self.token.kind) {
             self.bump();
             Ok(Recovered::No)
-        } else if inedible.contains(&self.token.kind) {
+        } else if inedible.iter().any(|exp| exp.tok == &self.token.kind) {
             // leave it in the input
             Ok(Recovered::No)
         } else if self.token != token::Eof
@@ -593,13 +596,13 @@ impl<'a> Parser<'a> {
 
     /// Checks if the next token is `tok`, and returns `true` if so.
     ///
-    /// This method will automatically add `tok` to `expected_tokens` if `tok` is not
+    /// This method will automatically add `tok` to `expected_token_types` if `tok` is not
     /// encountered.
     #[inline]
-    fn check(&mut self, tok: &TokenKind) -> bool {
-        let is_present = self.token == *tok;
+    fn check(&mut self, exp: ExpTokenPair<'_>) -> bool {
+        let is_present = self.token == *exp.tok;
         if !is_present {
-            self.expected_tokens.push(TokenType::Token(tok.clone()));
+            self.expected_token_types.insert(exp.token_type);
         }
         is_present
     }
@@ -627,8 +630,8 @@ impl<'a> Parser<'a> {
     /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
     #[inline]
     #[must_use]
-    pub fn eat(&mut self, tok: &TokenKind) -> bool {
-        let is_present = self.check(tok);
+    pub fn eat(&mut self, exp: ExpTokenPair<'_>) -> bool {
+        let is_present = self.check(exp);
         if is_present {
             self.bump()
         }
@@ -639,22 +642,23 @@ impl<'a> Parser<'a> {
     /// An expectation is also added for diagnostics purposes.
     #[inline]
     #[must_use]
-    fn check_keyword(&mut self, kw: Symbol) -> bool {
-        self.expected_tokens.push(TokenType::Keyword(kw));
-        self.token.is_keyword(kw)
+    fn check_keyword(&mut self, exp: ExpKeywordPair) -> bool {
+        let is_keyword = self.token.is_keyword(exp.kw);
+        if !is_keyword {
+            self.expected_token_types.insert(exp.token_type);
+        }
+        is_keyword
     }
 
     #[inline]
     #[must_use]
-    fn check_keyword_case(&mut self, kw: Symbol, case: Case) -> bool {
-        if self.check_keyword(kw) {
-            return true;
-        }
-
+    fn check_keyword_case(&mut self, exp: ExpKeywordPair, case: Case) -> bool {
+        if self.check_keyword(exp) {
+            true
         // Do an ASCII case-insensitive match, because all keywords are ASCII.
-        if case == Case::Insensitive
+        } else if case == Case::Insensitive
             && let Some((ident, IdentIsRaw::No)) = self.token.ident()
-            && ident.as_str().eq_ignore_ascii_case(kw.as_str())
+            && ident.as_str().eq_ignore_ascii_case(exp.kw.as_str())
         {
             true
         } else {
@@ -667,13 +671,12 @@ impl<'a> Parser<'a> {
     // Public for rustc_builtin_macros and rustfmt usage.
     #[inline]
     #[must_use]
-    pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
-        if self.check_keyword(kw) {
+    pub fn eat_keyword(&mut self, exp: ExpKeywordPair) -> bool {
+        let is_keyword = self.check_keyword(exp);
+        if is_keyword {
             self.bump();
-            true
-        } else {
-            false
         }
+        is_keyword
     }
 
     /// Eats a keyword, optionally ignoring the case.
@@ -681,21 +684,19 @@ impl<'a> Parser<'a> {
     /// This is useful for recovery.
     #[inline]
     #[must_use]
-    fn eat_keyword_case(&mut self, kw: Symbol, case: Case) -> bool {
-        if self.eat_keyword(kw) {
-            return true;
-        }
-
-        if case == Case::Insensitive
+    fn eat_keyword_case(&mut self, exp: ExpKeywordPair, case: Case) -> bool {
+        if self.eat_keyword(exp) {
+            true
+        } else if case == Case::Insensitive
             && let Some((ident, IdentIsRaw::No)) = self.token.ident()
-            && ident.as_str().to_lowercase() == kw.as_str().to_lowercase()
+            && ident.as_str().to_lowercase() == exp.kw.as_str().to_lowercase()
         {
-            self.dcx().emit_err(errors::KwBadCase { span: ident.span, kw: kw.as_str() });
+            self.dcx().emit_err(errors::KwBadCase { span: ident.span, kw: exp.kw.as_str() });
             self.bump();
-            return true;
+            true
+        } else {
+            false
         }
-
-        false
     }
 
     /// If the next token is the given keyword, eats it and returns `true`.
@@ -704,19 +705,18 @@ impl<'a> Parser<'a> {
     #[inline]
     #[must_use]
     pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
-        if self.token.is_keyword(kw) {
+        let is_keyword = self.token.is_keyword(kw);
+        if is_keyword {
             self.bump();
-            true
-        } else {
-            false
         }
+        is_keyword
     }
 
     /// If the given word is not a keyword, signals an error.
     /// If the next token is not the given word, signals an error.
     /// Otherwise, eats it.
-    pub fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> {
-        if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) }
+    pub fn expect_keyword(&mut self, exp: ExpKeywordPair) -> PResult<'a, ()> {
+        if !self.eat_keyword(exp) { self.unexpected() } else { Ok(()) }
     }
 
     /// Is the given keyword `kw` followed by a non-reserved identifier?
@@ -725,13 +725,11 @@ impl<'a> Parser<'a> {
     }
 
     #[inline]
-    fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool {
-        if ok {
-            true
-        } else {
-            self.expected_tokens.push(typ);
-            false
+    fn check_or_expected(&mut self, ok: bool, token_type: TokenType) -> bool {
+        if !ok {
+            self.expected_token_types.insert(token_type);
         }
+        ok
     }
 
     fn check_ident(&mut self) -> bool {
@@ -774,22 +772,19 @@ impl<'a> Parser<'a> {
     /// Otherwise returns `false`.
     #[inline]
     fn check_plus(&mut self) -> bool {
-        self.check_or_expected(
-            self.token.is_like_plus(),
-            TokenType::Token(token::BinOp(token::Plus)),
-        )
+        self.check_or_expected(self.token.is_like_plus(), TokenType::Plus)
     }
 
     /// Eats the expected token if it's present possibly breaking
     /// compound tokens like multi-character operators in process.
     /// Returns `true` if the token was eaten.
-    fn break_and_eat(&mut self, expected: TokenKind) -> bool {
-        if self.token == expected {
+    fn break_and_eat(&mut self, exp: ExpTokenPair<'_>) -> bool {
+        if self.token == *exp.tok {
             self.bump();
             return true;
         }
         match self.token.kind.break_two_token_op(1) {
-            Some((first, second)) if first == expected => {
+            Some((first, second)) if first == *exp.tok => {
                 let first_span = self.psess.source_map().start_point(self.token.span);
                 let second_span = self.token.span.with_lo(first_span.hi());
                 self.token = Token::new(first, first_span);
@@ -806,7 +801,7 @@ impl<'a> Parser<'a> {
                 true
             }
             _ => {
-                self.expected_tokens.push(TokenType::Token(expected));
+                self.expected_token_types.insert(exp.token_type);
                 false
             }
         }
@@ -814,24 +809,24 @@ impl<'a> Parser<'a> {
 
     /// Eats `+` possibly breaking tokens like `+=` in process.
     fn eat_plus(&mut self) -> bool {
-        self.break_and_eat(token::BinOp(token::Plus))
+        self.break_and_eat(exp!(Plus))
     }
 
     /// Eats `&` possibly breaking tokens like `&&` in process.
     /// Signals an error if `&` is not eaten.
     fn expect_and(&mut self) -> PResult<'a, ()> {
-        if self.break_and_eat(token::BinOp(token::And)) { Ok(()) } else { self.unexpected() }
+        if self.break_and_eat(exp!(And)) { Ok(()) } else { self.unexpected() }
     }
 
     /// Eats `|` possibly breaking tokens like `||` in process.
     /// Signals an error if `|` was not eaten.
     fn expect_or(&mut self) -> PResult<'a, ()> {
-        if self.break_and_eat(token::BinOp(token::Or)) { Ok(()) } else { self.unexpected() }
+        if self.break_and_eat(exp!(Or)) { Ok(()) } else { self.unexpected() }
     }
 
     /// Eats `<` possibly breaking tokens like `<<` in process.
     fn eat_lt(&mut self) -> bool {
-        let ate = self.break_and_eat(token::Lt);
+        let ate = self.break_and_eat(exp!(Lt));
         if ate {
             // See doc comment for `unmatched_angle_bracket_count`.
             self.unmatched_angle_bracket_count += 1;
@@ -849,7 +844,7 @@ impl<'a> Parser<'a> {
     /// Eats `>` possibly breaking tokens like `>>` in process.
     /// Signals an error if `>` was not eaten.
     fn expect_gt(&mut self) -> PResult<'a, ()> {
-        if self.break_and_eat(token::Gt) {
+        if self.break_and_eat(exp!(Gt)) {
             // See doc comment for `unmatched_angle_bracket_count`.
             if self.unmatched_angle_bracket_count > 0 {
                 self.unmatched_angle_bracket_count -= 1;
@@ -861,14 +856,14 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Checks if the next token is contained within `kets`, and returns `true` if so.
+    /// Checks if the next token is contained within `closes`, and returns `true` if so.
     fn expect_any_with_type(
         &mut self,
-        kets_expected: &[&TokenKind],
-        kets_not_expected: &[&TokenKind],
+        closes_expected: &[ExpTokenPair<'_>],
+        closes_not_expected: &[&TokenKind],
     ) -> bool {
-        kets_expected.iter().any(|k| self.check(k))
-            || kets_not_expected.iter().any(|k| self.check_noexpect(k))
+        closes_expected.iter().any(|&close| self.check(close))
+            || closes_not_expected.iter().any(|k| self.check_noexpect(k))
     }
 
     /// Parses a sequence until the specified delimiters. The function
@@ -876,9 +871,9 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_seq_to_before_tokens<T>(
         &mut self,
-        kets_expected: &[&TokenKind],
-        kets_not_expected: &[&TokenKind],
-        sep: SeqSep,
+        closes_expected: &[ExpTokenPair<'_>],
+        closes_not_expected: &[&TokenKind],
+        sep: SeqSep<'_>,
         mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
         let mut first = true;
@@ -886,17 +881,17 @@ impl<'a> Parser<'a> {
         let mut trailing = Trailing::No;
         let mut v = ThinVec::new();
 
-        while !self.expect_any_with_type(kets_expected, kets_not_expected) {
+        while !self.expect_any_with_type(closes_expected, closes_not_expected) {
             if let token::CloseDelim(..) | token::Eof = self.token.kind {
                 break;
             }
-            if let Some(t) = &sep.sep {
+            if let Some(exp) = sep.sep {
                 if first {
                     // no separator for the first element
                     first = false;
                 } else {
                     // check for separator
-                    match self.expect(t) {
+                    match self.expect(exp) {
                         Ok(Recovered::No) => {
                             self.current_closure.take();
                         }
@@ -907,7 +902,7 @@ impl<'a> Parser<'a> {
                         }
                         Err(mut expect_err) => {
                             let sp = self.prev_token.span.shrink_to_hi();
-                            let token_str = pprust::token_kind_to_string(t);
+                            let token_str = pprust::token_kind_to_string(exp.tok);
 
                             match self.current_closure.take() {
                                 Some(closure_spans) if self.token == TokenKind::Semi => {
@@ -927,7 +922,7 @@ impl<'a> Parser<'a> {
 
                                 _ => {
                                     // Attempt to keep parsing if it was a similar separator.
-                                    if let Some(tokens) = t.similar_tokens() {
+                                    if let Some(tokens) = exp.tok.similar_tokens() {
                                         if tokens.contains(&self.token.kind) {
                                             self.bump();
                                         }
@@ -977,15 +972,17 @@ impl<'a> Parser<'a> {
                                     // Parsing failed, therefore it must be something more serious
                                     // than just a missing separator.
                                     for xx in &e.children {
-                                        // propagate the help message from sub error 'e' to main error 'expect_err;
+                                        // Propagate the help message from sub error `e` to main
+                                        // error `expect_err`.
                                         expect_err.children.push(xx.clone());
                                     }
                                     e.cancel();
                                     if self.token == token::Colon {
-                                        // we will try to recover in `maybe_recover_struct_lit_bad_delims`
+                                        // We will try to recover in
+                                        // `maybe_recover_struct_lit_bad_delims`.
                                         return Err(expect_err);
-                                    } else if let [token::CloseDelim(Delimiter::Parenthesis)] =
-                                        kets_expected
+                                    } else if let [exp] = closes_expected
+                                        && exp.token_type == TokenType::CloseParen
                                     {
                                         return Err(expect_err);
                                     } else {
@@ -999,7 +996,7 @@ impl<'a> Parser<'a> {
                 }
             }
             if sep.trailing_sep_allowed
-                && self.expect_any_with_type(kets_expected, kets_not_expected)
+                && self.expect_any_with_type(closes_expected, closes_not_expected)
             {
                 trailing = Trailing::Yes;
                 break;
@@ -1019,7 +1016,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, ()> {
         let initial_semicolon = self.token.span;
 
-        while self.eat(&TokenKind::Semi) {
+        while self.eat(exp!(Semi)) {
             let _ = self.parse_stmt_without_recovery(false, ForceCollect::No).unwrap_or_else(|e| {
                 e.cancel();
                 None
@@ -1075,11 +1072,11 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_seq_to_before_end<T>(
         &mut self,
-        ket: &TokenKind,
-        sep: SeqSep,
+        close: ExpTokenPair<'_>,
+        sep: SeqSep<'_>,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
-        self.parse_seq_to_before_tokens(&[ket], &[], sep, f)
+        self.parse_seq_to_before_tokens(&[close], &[], sep, f)
     }
 
     /// Parses a sequence, including only the closing delimiter. The function
@@ -1087,15 +1084,15 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_seq_to_end<T>(
         &mut self,
-        ket: &TokenKind,
-        sep: SeqSep,
+        close: ExpTokenPair<'_>,
+        sep: SeqSep<'_>,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
-        let (val, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
-        if matches!(recovered, Recovered::No) && !self.eat(ket) {
+        let (val, trailing, recovered) = self.parse_seq_to_before_end(close, sep, f)?;
+        if matches!(recovered, Recovered::No) && !self.eat(close) {
             self.dcx().span_delayed_bug(
                 self.token.span,
-                "recovered but `parse_seq_to_before_end` did not give us the ket token",
+                "recovered but `parse_seq_to_before_end` did not give us the close token",
             );
         }
         Ok((val, trailing))
@@ -1106,13 +1103,13 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_unspanned_seq<T>(
         &mut self,
-        bra: &TokenKind,
-        ket: &TokenKind,
-        sep: SeqSep,
+        open: ExpTokenPair<'_>,
+        close: ExpTokenPair<'_>,
+        sep: SeqSep<'_>,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
-        self.expect(bra)?;
-        self.parse_seq_to_end(ket, sep, f)
+        self.expect(open)?;
+        self.parse_seq_to_end(close, sep, f)
     }
 
     /// Parses a comma-separated sequence, including both delimiters.
@@ -1120,15 +1117,11 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_delim_comma_seq<T>(
         &mut self,
-        delim: Delimiter,
+        open: ExpTokenPair<'_>,
+        close: ExpTokenPair<'_>,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
-        self.parse_unspanned_seq(
-            &token::OpenDelim(delim),
-            &token::CloseDelim(delim),
-            SeqSep::trailing_allowed(token::Comma),
-            f,
-        )
+        self.parse_unspanned_seq(open, close, SeqSep::trailing_allowed(exp!(Comma)), f)
     }
 
     /// Parses a comma-separated sequence delimited by parentheses (e.g. `(x, y)`).
@@ -1138,7 +1131,7 @@ impl<'a> Parser<'a> {
         &mut self,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
-        self.parse_delim_comma_seq(Delimiter::Parenthesis, f)
+        self.parse_delim_comma_seq(exp!(OpenParen), exp!(CloseParen), f)
     }
 
     /// Advance the parser by one token using provided token as the next one.
@@ -1154,7 +1147,7 @@ impl<'a> Parser<'a> {
         self.token_spacing = next_spacing;
 
         // Diagnostics.
-        self.expected_tokens.clear();
+        self.expected_token_types.clear();
     }
 
     /// Advance the parser by one token.
@@ -1191,7 +1184,7 @@ impl<'a> Parser<'a> {
         if dist == 1 {
             // The index is zero because the tree cursor's index always points
             // to the next token to be gotten.
-            match self.token_cursor.tree_cursor.look_ahead(0) {
+            match self.token_cursor.curr.curr() {
                 Some(tree) => {
                     // Indexing stayed within the current token tree.
                     match tree {
@@ -1201,12 +1194,13 @@ impl<'a> Parser<'a> {
                                 return looker(&Token::new(token::OpenDelim(delim), dspan.open));
                             }
                         }
-                    };
+                    }
                 }
                 None => {
                     // The tree cursor lookahead went (one) past the end of the
                     // current token tree. Try to return a close delimiter.
-                    if let Some(&(_, span, _, delim)) = self.token_cursor.stack.last()
+                    if let Some(last) = self.token_cursor.stack.last()
+                        && let Some(&TokenTree::Delimited(span, _, delim, _)) = last.curr()
                         && !delim.skip()
                     {
                         // We are not in the outermost token stream, so we have
@@ -1243,11 +1237,11 @@ impl<'a> Parser<'a> {
     /// Parses asyncness: `async` or nothing.
     fn parse_coroutine_kind(&mut self, case: Case) -> Option<CoroutineKind> {
         let span = self.token.uninterpolated_span();
-        if self.eat_keyword_case(kw::Async, case) {
+        if self.eat_keyword_case(exp!(Async), case) {
             // FIXME(gen_blocks): Do we want to unconditionally parse `gen` and then
             // error if edition <= 2024, like we do with async and edition <= 2018?
             if self.token.uninterpolated_span().at_least_rust_2024()
-                && self.eat_keyword_case(kw::Gen, case)
+                && self.eat_keyword_case(exp!(Gen), case)
             {
                 let gen_span = self.prev_token.uninterpolated_span();
                 Some(CoroutineKind::AsyncGen {
@@ -1263,7 +1257,7 @@ impl<'a> Parser<'a> {
                 })
             }
         } else if self.token.uninterpolated_span().at_least_rust_2024()
-            && self.eat_keyword_case(kw::Gen, case)
+            && self.eat_keyword_case(exp!(Gen), case)
         {
             Some(CoroutineKind::Gen {
                 span,
@@ -1277,9 +1271,9 @@ impl<'a> Parser<'a> {
 
     /// Parses fn unsafety: `unsafe`, `safe` or nothing.
     fn parse_safety(&mut self, case: Case) -> Safety {
-        if self.eat_keyword_case(kw::Unsafe, case) {
+        if self.eat_keyword_case(exp!(Unsafe), case) {
             Safety::Unsafe(self.prev_token.uninterpolated_span())
-        } else if self.eat_keyword_case(kw::Safe, case) {
+        } else if self.eat_keyword_case(exp!(Safe), case) {
             Safety::Safe(self.prev_token.uninterpolated_span())
         } else {
             Safety::Default
@@ -1305,7 +1299,7 @@ impl<'a> Parser<'a> {
         if (self.check_const_closure() == is_closure)
             && !self
                 .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block())
-            && self.eat_keyword_case(kw::Const, case)
+            && self.eat_keyword_case(exp!(Const), case)
         {
             Const::Yes(self.prev_token.uninterpolated_span())
         } else {
@@ -1318,7 +1312,7 @@ impl<'a> Parser<'a> {
         if pat {
             self.psess.gated_spans.gate(sym::inline_const_pat, span);
         }
-        self.expect_keyword(kw::Const)?;
+        self.expect_keyword(exp!(Const))?;
         let (attrs, blk) = self.parse_inner_attrs_and_block()?;
         let anon_const = AnonConst {
             id: DUMMY_NODE_ID,
@@ -1330,19 +1324,19 @@ impl<'a> Parser<'a> {
 
     /// Parses mutability (`mut` or nothing).
     fn parse_mutability(&mut self) -> Mutability {
-        if self.eat_keyword(kw::Mut) { Mutability::Mut } else { Mutability::Not }
+        if self.eat_keyword(exp!(Mut)) { Mutability::Mut } else { Mutability::Not }
     }
 
     /// Parses reference binding mode (`ref`, `ref mut`, or nothing).
     fn parse_byref(&mut self) -> ByRef {
-        if self.eat_keyword(kw::Ref) { ByRef::Yes(self.parse_mutability()) } else { ByRef::No }
+        if self.eat_keyword(exp!(Ref)) { ByRef::Yes(self.parse_mutability()) } else { ByRef::No }
     }
 
     /// Possibly parses mutability (`const` or `mut`).
     fn parse_const_or_mut(&mut self) -> Option<Mutability> {
-        if self.eat_keyword(kw::Mut) {
+        if self.eat_keyword(exp!(Mut)) {
             Some(Mutability::Mut)
-        } else if self.eat_keyword(kw::Const) {
+        } else if self.eat_keyword(exp!(Const)) {
             Some(Mutability::Not)
         } else {
             None
@@ -1373,7 +1367,7 @@ impl<'a> Parser<'a> {
     fn parse_attr_args(&mut self) -> PResult<'a, AttrArgs> {
         Ok(if let Some(args) = self.parse_delim_args_inner() {
             AttrArgs::Delimited(args)
-        } else if self.eat(&token::Eq) {
+        } else if self.eat(exp!(Eq)) {
             let eq_span = self.prev_token.span;
             AttrArgs::Eq { eq_span, expr: self.parse_expr_force_collect()? }
         } else {
@@ -1382,9 +1376,9 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_delim_args_inner(&mut self) -> Option<DelimArgs> {
-        let delimited = self.check(&token::OpenDelim(Delimiter::Parenthesis))
-            || self.check(&token::OpenDelim(Delimiter::Bracket))
-            || self.check(&token::OpenDelim(Delimiter::Brace));
+        let delimited = self.check(exp!(OpenParen))
+            || self.check(exp!(OpenBracket))
+            || self.check(exp!(OpenBrace));
 
         delimited.then(|| {
             let TokenTree::Delimited(dspan, _, delim, tokens) = self.parse_token_tree() else {
@@ -1398,9 +1392,10 @@ impl<'a> Parser<'a> {
     pub fn parse_token_tree(&mut self) -> TokenTree {
         match self.token.kind {
             token::OpenDelim(..) => {
-                // Grab the tokens within the delimiters.
-                let stream = self.token_cursor.tree_cursor.stream.clone();
-                let (_, span, spacing, delim) = *self.token_cursor.stack.last().unwrap();
+                // Clone the `TokenTree::Delimited` that we are currently
+                // within. That's what we are going to return.
+                let tree = self.token_cursor.stack.last().unwrap().curr().unwrap().clone();
+                debug_assert_matches!(tree, TokenTree::Delimited(..));
 
                 // Advance the token cursor through the entire delimited
                 // sequence. After getting the `OpenDelim` we are *within* the
@@ -1420,7 +1415,7 @@ impl<'a> Parser<'a> {
 
                 // Consume close delimiter
                 self.bump();
-                TokenTree::Delimited(span, spacing, delim, stream)
+                tree
             }
             token::CloseDelim(_) | token::Eof => unreachable!(),
             _ => {
@@ -1462,7 +1457,7 @@ impl<'a> Parser<'a> {
     pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
         maybe_whole!(self, NtVis, |vis| vis.into_inner());
 
-        if !self.eat_keyword(kw::Pub) {
+        if !self.eat_keyword(exp!(Pub)) {
             // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no
             // keyword to grab a span from for inherited visibility; an empty span at the
             // beginning of the current token would seem to be the "Schelling span".
@@ -1474,7 +1469,7 @@ impl<'a> Parser<'a> {
         }
         let lo = self.prev_token.span;
 
-        if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
+        if self.check(exp!(OpenParen)) {
             // We don't `self.bump()` the `(` yet because this might be a struct definition where
             // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
             // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
@@ -1484,7 +1479,7 @@ impl<'a> Parser<'a> {
                 self.bump(); // `(`
                 self.bump(); // `in`
                 let path = self.parse_path(PathStyle::Mod)?; // `path`
-                self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
+                self.expect(exp!(CloseParen))?; // `)`
                 let vis = VisibilityKind::Restricted {
                     path: P(path),
                     id: ast::DUMMY_NODE_ID,
@@ -1501,7 +1496,7 @@ impl<'a> Parser<'a> {
                 // Parse `pub(crate)`, `pub(self)`, or `pub(super)`.
                 self.bump(); // `(`
                 let path = self.parse_path(PathStyle::Mod)?; // `crate`/`super`/`self`
-                self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
+                self.expect(exp!(CloseParen))?; // `)`
                 let vis = VisibilityKind::Restricted {
                     path: P(path),
                     id: ast::DUMMY_NODE_ID,
@@ -1527,7 +1522,7 @@ impl<'a> Parser<'a> {
     fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
         self.bump(); // `(`
         let path = self.parse_path(PathStyle::Mod)?;
-        self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
+        self.expect(exp!(CloseParen))?; // `)`
 
         let path_str = pprust::path_to_string(&path);
         self.dcx()
@@ -1538,7 +1533,7 @@ impl<'a> Parser<'a> {
 
     /// Parses `extern string_literal?`.
     fn parse_extern(&mut self, case: Case) -> Extern {
-        if self.eat_keyword_case(kw::Extern, case) {
+        if self.eat_keyword_case(exp!(Extern), case) {
             let mut extern_span = self.prev_token.span;
             let abi = self.parse_abi();
             if let Some(abi) = abi {
@@ -1578,7 +1573,7 @@ impl<'a> Parser<'a> {
 
     /// Checks for `::` or, potentially, `:::` and then look ahead after it.
     fn check_path_sep_and_look_ahead(&mut self, looker: impl Fn(&Token) -> bool) -> bool {
-        if self.check(&token::PathSep) {
+        if self.check(exp!(PathSep)) {
             if self.may_recover() && self.look_ahead(1, |t| t.kind == token::Colon) {
                 debug_assert!(!self.look_ahead(1, &looker), "Looker must not match on colon");
                 self.look_ahead(2, looker)
@@ -1642,8 +1637,8 @@ impl<'a> Parser<'a> {
         DebugParser { parser: self, lookahead }
     }
 
-    pub fn clear_expected_tokens(&mut self) {
-        self.expected_tokens.clear();
+    pub fn clear_expected_token_types(&mut self) {
+        self.expected_token_types.clear();
     }
 
     pub fn approx_token_stream_pos(&self) -> u32 {