Skip to content

Commit 7504b9b

Browse files
committed
Avoid double-collection for expression nonterminals
1 parent fe60f19 commit 7504b9b

File tree

3 files changed

+17
-17
lines changed

3 files changed

+17
-17
lines changed

compiler/rustc_parse/src/parser/expr.rs

+15
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,21 @@ impl<'a> Parser<'a> {
9292
self.parse_expr_res(Restrictions::empty(), None)
9393
}
9494

95+
/// Parses an expression, forcing tokens to be collected
96+
pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
97+
// If we have outer attributes, then the call to `collect_tokens_trailing_token`
98+
// will be made for us.
99+
if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) {
100+
self.parse_expr()
101+
} else {
102+
// If we don't have outer attributes, then we need to ensure
103+
// that collection happens by using `collect_tokens_no_attrs`.
104+
// Expression don't support custom inner attributes, so `parse_expr`
105+
// will never try to collect tokens if we don't have outer attributes.
106+
self.collect_tokens_no_attrs(|this| this.parse_expr())
107+
}
108+
}
109+
95110
pub(super) fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
96111
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
97112
}

compiler/rustc_parse/src/parser/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ impl<'a> Parser<'a> {
987987
}
988988

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

993993
match &expr.kind {

compiler/rustc_parse/src/parser/nonterminal.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -128,22 +128,7 @@ impl<'a> Parser<'a> {
128128
})?)
129129
}
130130

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

0 commit comments

Comments
 (0)