Skip to content

Commit

Permalink
Avoid double-collection for expression nonterminals
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron1011 committed Mar 25, 2021
1 parent fe60f19 commit 7504b9b
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 17 deletions.
15 changes: 15 additions & 0 deletions compiler/rustc_parse/src/parser/expr.rs
Expand Up @@ -92,6 +92,21 @@ impl<'a> Parser<'a> {
self.parse_expr_res(Restrictions::empty(), None)
}

/// Parses an expression, forcing tokens to be collected
pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
// If we have outer attributes, then the call to `collect_tokens_trailing_token`
// will be made for us.
if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) {
self.parse_expr()
} else {
// If we don't have outer attributes, then we need to ensure
// that collection happens by using `collect_tokens_no_attrs`.
// Expression don't support custom inner attributes, so `parse_expr`
// will never try to collect tokens if we don't have outer attributes.
self.collect_tokens_no_attrs(|this| this.parse_expr())
}
}

pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/mod.rs
Expand Up @@ -987,7 +987,7 @@ impl<'a> Parser<'a> {
}

// Collect tokens because they are used during lowering to HIR.
let expr = self.collect_tokens_no_attrs(|this| this.parse_expr())?;
let expr = self.parse_expr_force_collect()?;
let span = expr.span;

match &expr.kind {
Expand Down
17 changes: 1 addition & 16 deletions compiler/rustc_parse/src/parser/nonterminal.rs
Expand Up @@ -128,22 +128,7 @@ impl<'a> Parser<'a> {
})?)
}

// If there are attributes present, then `parse_expr` will end up collecting tokens,
// turning the outer `collect_tokens_no_attrs` into a no-op due to the already present
// tokens. If there are *not* attributes present, then the outer
// `collect_tokens_no_attrs` will ensure that we will end up collecting tokens for the
// expressions.
//
// This is less efficient than it could be, since the outer `collect_tokens_no_attrs`
// still needs to snapshot the `TokenCursor` before calling `parse_expr`, even when
// `parse_expr` will end up collecting tokens. Ideally, this would work more like
// `parse_item`, and take in a `ForceCollect` parameter. However, this would require
// adding a `ForceCollect` parameter in a bunch of places in expression parsing
// for little gain. If the perf impact from this turns out to be noticeable, we should
// revisit this apporach.
NonterminalKind::Expr => {
token::NtExpr(self.collect_tokens_no_attrs(|this| this.parse_expr())?)
}
NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?),
NonterminalKind::Literal => {
// The `:literal` matcher does not support attributes
token::NtLiteral(
Expand Down

0 comments on commit 7504b9b

Please sign in to comment.