about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-08-12 09:28:35 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2025-08-14 15:31:29 +1000
commit145b84721aae8e62d90b0fe40e8f796289ff7303 (patch)
treea52327d35782b43f7d9e8e12616e647a995e9d48
parent2fd855fbfc8239285aa2d596f76a8cc75e17ce02 (diff)
downloadrust-145b84721aae8e62d90b0fe40e8f796289ff7303.tar.gz
rust-145b84721aae8e62d90b0fe40e8f796289ff7303.zip
Sometimes skip over tokens in `parse_token_tree`.
This sometimes avoids a lot of `bump` calls.
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs6
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs23
2 files changed, 23 insertions, 6 deletions
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index e55399adfb8..f4f35a4d2ee 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -907,6 +907,12 @@ impl TokenTreeCursor {
     pub fn bump(&mut self) {
         self.index += 1;
     }
+
+    // For skipping ahead in rare circumstances.
+    #[inline]
+    pub fn bump_to_end(&mut self) {
+        self.index = self.stream.len();
+    }
 }
 
 /// A `TokenStream` cursor that produces `Token`s. It's a bit odd that
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 90491e53249..3be575c6b15 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1389,15 +1389,26 @@ impl<'a> Parser<'a> {
             // matching `CloseDelim` we are *after* the delimited sequence,
             // i.e. at depth `d - 1`.
             let target_depth = self.token_cursor.stack.len() - 1;
-            loop {
-                // Advance one token at a time, so `TokenCursor::next()`
-                // can capture these tokens if necessary.
+
+            if let Capturing::No = self.capture_state.capturing {
+                // We are not capturing tokens, so skip to the end of the
+                // delimited sequence. This is a perf win when dealing with
+                // declarative macros that pass large `tt` fragments through
+                // multiple rules, as seen in the uom-0.37.0 crate.
+                self.token_cursor.curr.bump_to_end();
                 self.bump();
-                if self.token_cursor.stack.len() == target_depth {
-                    debug_assert!(self.token.kind.close_delim().is_some());
-                    break;
+                debug_assert_eq!(self.token_cursor.stack.len(), target_depth);
+            } else {
+                loop {
+                    // Advance one token at a time, so `TokenCursor::next()`
+                    // can capture these tokens if necessary.
+                    self.bump();
+                    if self.token_cursor.stack.len() == target_depth {
+                        break;
+                    }
                 }
             }
+            debug_assert!(self.token.kind.close_delim().is_some());
 
             // Consume close delimiter
             self.bump();