]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_parse/src/parser/nonterminal.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / compiler / rustc_parse / src / parser / nonterminal.rs
index 6e25209f0905ebe9222be9744a5273ce44f13a06..a84ae5151442d8c9f0c6c5c1d5b53bebe45612c2 100644 (file)
@@ -108,7 +108,9 @@ impl<'a> Parser<'a> {
                 }
             },
             NonterminalKind::Block => {
-                token::NtBlock(self.collect_tokens(|this| this.parse_block())?)
+                // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`),
+                // the ':block' matcher does not support them
+                token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
             }
             NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
                 Some(s) => token::NtStmt(s),
@@ -117,19 +119,41 @@ impl<'a> Parser<'a> {
                 }
             },
             NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => {
-                token::NtPat(self.collect_tokens(|this| match kind {
-                    NonterminalKind::Pat2018 { .. } => this.parse_pat(None),
+                token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
+                    NonterminalKind::Pat2018 { .. } => this.parse_pat_no_top_alt(None),
                     NonterminalKind::Pat2021 { .. } => {
-                        this.parse_top_pat(GateOr::Yes, RecoverComma::No)
+                        this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
                     }
                     _ => unreachable!(),
                 })?)
             }
-            NonterminalKind::Expr => token::NtExpr(self.collect_tokens(|this| this.parse_expr())?),
+
+            // 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::Literal => {
-                token::NtLiteral(self.collect_tokens(|this| this.parse_literal_maybe_minus())?)
+                // The `:literal` matcher does not support attributes
+                token::NtLiteral(
+                    self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?,
+                )
+            }
+
+            NonterminalKind::Ty => {
+                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty())?)
             }
-            NonterminalKind::Ty => token::NtTy(self.collect_tokens(|this| this.parse_ty())?),
             // this could be handled like a token, since it is one
             NonterminalKind::Ident => {
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
@@ -141,15 +165,15 @@ impl<'a> Parser<'a> {
                     return Err(self.struct_span_err(self.token.span, msg));
                 }
             }
-            NonterminalKind::Path => {
-                token::NtPath(self.collect_tokens(|this| this.parse_path(PathStyle::Type))?)
-            }
+            NonterminalKind::Path => token::NtPath(
+                self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?,
+            ),
             NonterminalKind::Meta => {
-                token::NtMeta(P(self.collect_tokens(|this| this.parse_attr_item(false))?))
+                token::NtMeta(P(self.collect_tokens_no_attrs(|this| this.parse_attr_item(false))?))
             }
             NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
             NonterminalKind::Vis => token::NtVis(
-                self.collect_tokens(|this| this.parse_visibility(FollowedByType::Yes))?,
+                self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?,
             ),
             NonterminalKind::Lifetime => {
                 if self.check_lifetime() {