about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser/mod.rs
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2024-07-12 13:20:24 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2024-07-12 13:35:24 +1000
commit100f3fd133d928e9c86cff202fa32e5e4d0ce6c7 (patch)
treeac48e5de185f654e0be0900b8bbadae3dd982269 /compiler/rustc_parse/src/parser/mod.rs
parentebe1305b1e0bb32913b309ce65bd97106532ad6a (diff)
downloadrust-100f3fd133d928e9c86cff202fa32e5e4d0ce6c7.tar.gz
rust-100f3fd133d928e9c86cff202fa32e5e4d0ce6c7.zip
Add a new special case to `Parser::look_ahead`.
This new special case is simpler than the old special case because it
only is used when `dist == 1`. But that's still enough to cover ~98% of
cases. This results in equivalent performance to the old special case,
and identical behaviour as the general case.
Diffstat (limited to 'compiler/rustc_parse/src/parser/mod.rs')
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs29
1 files changed, 29 insertions, 0 deletions
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index f906a2ecab7..ef9b3aabc61 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1118,6 +1118,35 @@ impl<'a> Parser<'a> {
             return looker(&self.token);
         }
 
+        // Typically around 98% of the `dist > 0` cases have `dist == 1`, so we
+        // have a fast special case for that.
+        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) {
+                Some(tree) => {
+                    // Indexing stayed within the current token tree.
+                    return match tree {
+                        TokenTree::Token(token, _) => looker(token),
+                        TokenTree::Delimited(dspan, _, delim, _) => {
+                            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()
+                        && delim != Delimiter::Invisible
+                    {
+                        // We are not in the outermost token stream, so we have
+                        // delimiters. Also, those delimiters are not skipped.
+                        return looker(&Token::new(token::CloseDelim(delim), span.close));
+                    }
+                }
+            }
+        }
+
         // Just clone the token cursor and use `next`, skipping delimiters as
         // necessary. Slow but simple.
         let mut cursor = self.token_cursor.clone();