about summary refs log tree commit diff
path: root/compiler/rustc_parse/src
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2022-04-20 12:22:42 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2022-04-20 12:28:26 +1000
commitb09522a634f5c6c53dd01ad60a37b6503355ce88 (patch)
tree7b793a4141b79ce978966e7903e34aed7f91c29a /compiler/rustc_parse/src
parent3cd5e346170437f844d18c17d3f870dc4722c96a (diff)
downloadrust-b09522a634f5c6c53dd01ad60a37b6503355ce88.tar.gz
rust-b09522a634f5c6c53dd01ad60a37b6503355ce88.zip
Remove the loop from `Parser::bump()`.
The loop is there to handle a `NoDelim` open/close token. This commit
changes `TokenCursor::inlined_next` so it never returns such a token.
This is a performance win because the conditional test in `bump()` is
removed.

If the parser needs changing in the future to handle `NoDelim` tokens,
then `inlined_next()` can easily be changed to return them.
Diffstat (limited to 'compiler/rustc_parse/src')
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs63
1 files changed, 34 insertions, 29 deletions
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index a276fb53895..173e0c2d529 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -242,12 +242,17 @@ struct TokenCursorFrame {
     delim: token::DelimToken,
     span: DelimSpan,
     tree_cursor: tokenstream::Cursor,
-    close_delim: bool,
+    need_to_produce_close_delim: bool,
 }
 
 impl TokenCursorFrame {
-    fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream, close_delim: bool) -> Self {
-        TokenCursorFrame { delim, span, tree_cursor: tts.into_trees(), close_delim }
+    fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self {
+        TokenCursorFrame {
+            delim,
+            span,
+            tree_cursor: tts.into_trees(),
+            need_to_produce_close_delim: delim != DelimToken::NoDelim,
+        }
     }
 }
 
@@ -261,28 +266,32 @@ impl TokenCursor {
     fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
         loop {
             if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing() {
-                return match tree {
+                match tree {
                     TokenTree::Token(token) => match (desugar_doc_comments, &token) {
                         (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
-                            self.desugar(attr_style, data, span)
+                            return self.desugar(attr_style, data, span);
                         }
-                        _ => (token, spacing),
+                        _ => return (token, spacing),
                     },
                     TokenTree::Delimited(sp, delim, tts) => {
                         // Set `open_delim` to true here because we deal with it immediately.
-                        let frame = TokenCursorFrame::new(sp, delim, tts, false);
+                        let frame = TokenCursorFrame::new(sp, delim, tts);
                         self.stack.push(mem::replace(&mut self.frame, frame));
-                        (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone)
+                        if delim != DelimToken::NoDelim {
+                            return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
+                        }
+                        // No open delimeter to return; continue on to the next iteration.
                     }
                 };
-            } else if !self.frame.close_delim {
-                self.frame.close_delim = true;
+            } else if self.frame.need_to_produce_close_delim {
+                self.frame.need_to_produce_close_delim = false;
                 return (
                     Token::new(token::CloseDelim(self.frame.delim), self.frame.span.close),
                     Spacing::Alone,
                 );
             } else if let Some(frame) = self.stack.pop() {
                 self.frame = frame;
+                // Back to the parent frame; continue on to the next iteration.
             } else {
                 return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
             }
@@ -333,7 +342,6 @@ impl TokenCursor {
                         .cloned()
                         .collect::<TokenStream>()
                 },
-                true,
             ),
         ));
 
@@ -422,7 +430,7 @@ impl<'a> Parser<'a> {
         desugar_doc_comments: bool,
         subparser_name: Option<&'static str>,
     ) -> Self {
-        let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens, true);
+        let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
 
         let mut parser = Parser {
             sess,
@@ -993,24 +1001,21 @@ impl<'a> Parser<'a> {
     /// Advance the parser by one token.
     pub fn bump(&mut self) {
         let fallback_span = self.token.span;
-        loop {
-            let (mut next, spacing) = self.token_cursor.inlined_next(self.desugar_doc_comments);
-            self.token_cursor.num_next_calls += 1;
-            // We've retrieved an token from the underlying
-            // cursor, so we no longer need to worry about
-            // an unglued token. See `break_and_eat` for more details
-            self.token_cursor.break_last_token = false;
-            if next.span.is_dummy() {
-                // Tweak the location for better diagnostics, but keep syntactic context intact.
-                next.span = fallback_span.with_ctxt(next.span.ctxt());
-            }
-            if !matches!(
-                next.kind,
-                token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
-            ) {
-                return self.inlined_bump_with((next, spacing));
-            }
+        let (mut next, spacing) = self.token_cursor.inlined_next(self.desugar_doc_comments);
+        self.token_cursor.num_next_calls += 1;
+        // We've retrieved an token from the underlying
+        // cursor, so we no longer need to worry about
+        // an unglued token. See `break_and_eat` for more details
+        self.token_cursor.break_last_token = false;
+        if next.span.is_dummy() {
+            // Tweak the location for better diagnostics, but keep syntactic context intact.
+            next.span = fallback_span.with_ctxt(next.span.ctxt());
         }
+        debug_assert!(!matches!(
+            next.kind,
+            token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
+        ));
+        self.inlined_bump_with((next, spacing))
     }
 
     /// Look-ahead `dist` tokens of `self.token` and get access to that token there.