about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2022-04-21 13:49:40 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2022-04-21 13:49:40 +1000
commit643e9f707ed4ca13a158b6e290b424e520809ca6 (patch)
tree7c737c276331b5891fabcd32be126ff1be6e7dff
parentcc4e3443ecf96f395e598b14af208d36a11ffb9f (diff)
downloadrust-643e9f707ed4ca13a158b6e290b424e520809ca6.tar.gz
rust-643e9f707ed4ca13a158b6e290b424e520809ca6.zip
Introduced `Cursor::next_with_spacing_ref`.
This lets us clone just the parts within a `TokenTree` that need
cloning, rather than the entire thing. This is a surprisingly large
performance win, up to 4% on `async-std-1.10.0`.
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs8
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs10
2 files changed, 13 insertions, 5 deletions
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 3321d3bf380..d609fa67205 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -583,6 +583,14 @@ impl Cursor {
         })
     }
 
+    #[inline]
+    pub fn next_with_spacing_ref(&mut self) -> Option<&TreeAndSpacing> {
+        self.stream.0.get(self.index).map(|tree| {
+            self.index += 1;
+            tree
+        })
+    }
+
     pub fn index(&self) -> usize {
         self.index
     }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index a620266247a..1686c5873e1 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -267,17 +267,17 @@ impl TokenCursor {
             // FIXME: we currently don't return `NoDelim` open/close delims. To fix #67062 we will
             // need to, whereupon the `delim != DelimToken::NoDelim` conditions below can be
             // removed, as well as the loop.
-            if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing() {
+            if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing_ref() {
                 match tree {
-                    TokenTree::Token(token) => match (desugar_doc_comments, &token) {
+                    &TokenTree::Token(ref token) => match (desugar_doc_comments, token) {
                         (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
                             return self.desugar(attr_style, data, span);
                         }
-                        _ => return (token, spacing),
+                        _ => return (token.clone(), *spacing),
                     },
-                    TokenTree::Delimited(sp, delim, tts) => {
+                    &TokenTree::Delimited(sp, delim, ref tts) => {
                         // Set `open_delim` to true here because we deal with it immediately.
-                        let frame = TokenCursorFrame::new(sp, delim, tts);
+                        let frame = TokenCursorFrame::new(sp, delim, tts.clone());
                         self.stack.push(mem::replace(&mut self.frame, frame));
                         if delim != DelimToken::NoDelim {
                             return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);