Skip to content

Commit b09522a

Browse files
committed
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.
1 parent 3cd5e34 commit b09522a

File tree

1 file changed

+34
-29
lines changed
  • compiler/rustc_parse/src/parser

1 file changed

+34
-29
lines changed

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,17 @@ struct TokenCursorFrame {
242242
delim: token::DelimToken,
243243
span: DelimSpan,
244244
tree_cursor: tokenstream::Cursor,
245-
close_delim: bool,
245+
need_to_produce_close_delim: bool,
246246
}
247247

248248
impl TokenCursorFrame {
249-
fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream, close_delim: bool) -> Self {
250-
TokenCursorFrame { delim, span, tree_cursor: tts.into_trees(), close_delim }
249+
fn new(span: DelimSpan, delim: DelimToken, tts: TokenStream) -> Self {
250+
TokenCursorFrame {
251+
delim,
252+
span,
253+
tree_cursor: tts.into_trees(),
254+
need_to_produce_close_delim: delim != DelimToken::NoDelim,
255+
}
251256
}
252257
}
253258

@@ -261,28 +266,32 @@ impl TokenCursor {
261266
fn inlined_next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
262267
loop {
263268
if let Some((tree, spacing)) = self.frame.tree_cursor.next_with_spacing() {
264-
return match tree {
269+
match tree {
265270
TokenTree::Token(token) => match (desugar_doc_comments, &token) {
266271
(true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
267-
self.desugar(attr_style, data, span)
272+
return self.desugar(attr_style, data, span);
268273
}
269-
_ => (token, spacing),
274+
_ => return (token, spacing),
270275
},
271276
TokenTree::Delimited(sp, delim, tts) => {
272277
// Set `open_delim` to true here because we deal with it immediately.
273-
let frame = TokenCursorFrame::new(sp, delim, tts, false);
278+
let frame = TokenCursorFrame::new(sp, delim, tts);
274279
self.stack.push(mem::replace(&mut self.frame, frame));
275-
(Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone)
280+
if delim != DelimToken::NoDelim {
281+
return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
282+
}
283+
// No open delimeter to return; continue on to the next iteration.
276284
}
277285
};
278-
} else if !self.frame.close_delim {
279-
self.frame.close_delim = true;
286+
} else if self.frame.need_to_produce_close_delim {
287+
self.frame.need_to_produce_close_delim = false;
280288
return (
281289
Token::new(token::CloseDelim(self.frame.delim), self.frame.span.close),
282290
Spacing::Alone,
283291
);
284292
} else if let Some(frame) = self.stack.pop() {
285293
self.frame = frame;
294+
// Back to the parent frame; continue on to the next iteration.
286295
} else {
287296
return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
288297
}
@@ -333,7 +342,6 @@ impl TokenCursor {
333342
.cloned()
334343
.collect::<TokenStream>()
335344
},
336-
true,
337345
),
338346
));
339347

@@ -422,7 +430,7 @@ impl<'a> Parser<'a> {
422430
desugar_doc_comments: bool,
423431
subparser_name: Option<&'static str>,
424432
) -> Self {
425-
let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens, true);
433+
let start_frame = TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, tokens);
426434

427435
let mut parser = Parser {
428436
sess,
@@ -993,24 +1001,21 @@ impl<'a> Parser<'a> {
9931001
/// Advance the parser by one token.
9941002
pub fn bump(&mut self) {
9951003
let fallback_span = self.token.span;
996-
loop {
997-
let (mut next, spacing) = self.token_cursor.inlined_next(self.desugar_doc_comments);
998-
self.token_cursor.num_next_calls += 1;
999-
// We've retrieved an token from the underlying
1000-
// cursor, so we no longer need to worry about
1001-
// an unglued token. See `break_and_eat` for more details
1002-
self.token_cursor.break_last_token = false;
1003-
if next.span.is_dummy() {
1004-
// Tweak the location for better diagnostics, but keep syntactic context intact.
1005-
next.span = fallback_span.with_ctxt(next.span.ctxt());
1006-
}
1007-
if !matches!(
1008-
next.kind,
1009-
token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
1010-
) {
1011-
return self.inlined_bump_with((next, spacing));
1012-
}
1004+
let (mut next, spacing) = self.token_cursor.inlined_next(self.desugar_doc_comments);
1005+
self.token_cursor.num_next_calls += 1;
1006+
// We've retrieved an token from the underlying
1007+
// cursor, so we no longer need to worry about
1008+
// an unglued token. See `break_and_eat` for more details
1009+
self.token_cursor.break_last_token = false;
1010+
if next.span.is_dummy() {
1011+
// Tweak the location for better diagnostics, but keep syntactic context intact.
1012+
next.span = fallback_span.with_ctxt(next.span.ctxt());
10131013
}
1014+
debug_assert!(!matches!(
1015+
next.kind,
1016+
token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
1017+
));
1018+
self.inlined_bump_with((next, spacing))
10141019
}
10151020

10161021
/// Look-ahead `dist` tokens of `self.token` and get access to that token there.

0 commit comments

Comments
 (0)