about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-06-08 23:07:22 +0000
committerbors <bors@rust-lang.org>2022-06-08 23:07:22 +0000
commit15f5622a53210099a19ab46ce2316494fb413d7c (patch)
tree633084d6eb33de525f55ae47663320370d9e6fc0 /compiler/rustc_parse/src/parser
parent7466d5492b2d28d2ba5114dbe71511a6502ac822 (diff)
parentcfc0677992662076f8fa65062a229aaae495f030 (diff)
downloadrust-15f5622a53210099a19ab46ce2316494fb413d7c.tar.gz
rust-15f5622a53210099a19ab46ce2316494fb413d7c.zip
Auto merge of #97896 - compiler-errors:rollup-mrl7ng0, r=compiler-errors
Rollup of 9 pull requests

Successful merges:

 - #97557 (Fix indices and remove some unwraps in arg mismatch algorithm)
 - #97830 (Add std::alloc::set_alloc_error_hook example)
 - #97856 (Don't suggest adding `let` in certain `if` conditions)
 - #97857 (Suggest escaping `box` as identifier)
 - #97871 (Suggest using `iter()` or `into_iter()` for `Vec`)
 - #97882 (Add regresion test for #67498)
 - #97883 (Remove `ignore-compare-mode-nll` annotations from tests)
 - #97891 (Update books)
 - #97894 (Fix polonius compare mode.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_parse/src/parser')
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs61
1 files changed, 57 insertions, 4 deletions
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 2ad3f3ec19d..ca7915ed17a 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -360,10 +360,7 @@ impl<'a> Parser<'a> {
             let mutbl = self.parse_mutability();
             self.parse_pat_ident(BindingMode::ByRef(mutbl))?
         } else if self.eat_keyword(kw::Box) {
-            // Parse `box pat`
-            let pat = self.parse_pat_with_range_pat(false, None)?;
-            self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span));
-            PatKind::Box(pat)
+            self.parse_pat_box()?
         } else if self.check_inline_const(0) {
             // Parse `const pat`
             let const_expr = self.parse_const_block(lo.to(self.token.span), true)?;
@@ -915,6 +912,62 @@ impl<'a> Parser<'a> {
         Ok(PatKind::TupleStruct(qself, path, fields))
     }
 
+    /// Are we sure this could not possibly be the start of a pattern?
+    ///
+    /// Currently, this only accounts for tokens that can follow identifiers
+    /// in patterns, but this can be extended as necessary.
+    fn isnt_pattern_start(&self) -> bool {
+        [
+            token::Eq,
+            token::Colon,
+            token::Comma,
+            token::Semi,
+            token::At,
+            token::OpenDelim(Delimiter::Brace),
+            token::CloseDelim(Delimiter::Brace),
+            token::CloseDelim(Delimiter::Parenthesis),
+        ]
+        .contains(&self.token.kind)
+    }
+
+    /// Parses `box pat`
+    fn parse_pat_box(&mut self) -> PResult<'a, PatKind> {
+        let box_span = self.prev_token.span;
+
+        if self.isnt_pattern_start() {
+            self.struct_span_err(
+                self.token.span,
+                format!("expected pattern, found {}", super::token_descr(&self.token)),
+            )
+            .span_note(box_span, "`box` is a reserved keyword")
+            .span_suggestion_verbose(
+                box_span.shrink_to_lo(),
+                "escape `box` to use it as an identifier",
+                "r#",
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
+
+            // We cannot use `parse_pat_ident()` since it will complain `box`
+            // is not an identifier.
+            let sub = if self.eat(&token::At) {
+                Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
+            } else {
+                None
+            };
+
+            Ok(PatKind::Ident(
+                BindingMode::ByValue(Mutability::Not),
+                Ident::new(kw::Box, box_span),
+                sub,
+            ))
+        } else {
+            let pat = self.parse_pat_with_range_pat(false, None)?;
+            self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
+            Ok(PatKind::Box(pat))
+        }
+    }
+
     /// Parses the fields of a struct-like pattern.
     fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<PatField>, bool)> {
         let mut fields = Vec::new();