about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs10
-rw-r--r--tests/ui/pattern/pattern-bad-ref-box-order.fixed14
-rw-r--r--tests/ui/pattern/pattern-bad-ref-box-order.rs14
-rw-r--r--tests/ui/pattern/pattern-bad-ref-box-order.stderr8
6 files changed, 55 insertions, 2 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 49a2c414467..83bbfeb2805 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -721,6 +721,9 @@ parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
 parse_switch_mut_let_order =
     switch the order of `mut` and `let`
 
+parse_switch_ref_box_order = switch the order of `ref` and `box`
+    .suggestion = swap them
+
 parse_ternary_operator = Rust has no ternary operator
     .help = use an `if-else` expression instead
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 7ce348619c6..0a919240ce5 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -138,6 +138,14 @@ pub(crate) enum InvalidVariableDeclarationSub {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_switch_ref_box_order)]
+pub(crate) struct SwitchRefBoxOrder {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = "box ref")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_invalid_comparison_operator)]
 pub(crate) struct InvalidComparisonOperator {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 15491cac56a..8f5f4459d64 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -5,8 +5,8 @@ use crate::errors::{
     ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
     InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
     PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
-    TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
-    UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
+    SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
+    TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
     UnexpectedVertVertInPattern,
 };
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
@@ -374,6 +374,12 @@ impl<'a> Parser<'a> {
         } else if self.eat_keyword(kw::Mut) {
             self.parse_pat_ident_mut(syntax_loc)?
         } else if self.eat_keyword(kw::Ref) {
+            if self.check_keyword(kw::Box) {
+                // Suggest `box ref` and quit parsing pattern to prevent series of
+                // misguided diagnostics from later stages of the compiler.
+                let span = self.prev_token.span.to(self.token.span);
+                return Err(self.sess.create_err(SwitchRefBoxOrder { span }));
+            }
             // Parse ref ident @ pat / ref mut ident @ pat
             let mutbl = self.parse_mutability();
             self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl), syntax_loc)?
diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.fixed b/tests/ui/pattern/pattern-bad-ref-box-order.fixed
new file mode 100644
index 00000000000..8825744a08b
--- /dev/null
+++ b/tests/ui/pattern/pattern-bad-ref-box-order.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![feature(box_patterns)]
+#![allow(dead_code)]
+
+fn foo(f: Option<Box<i32>>) {
+    match f {
+        Some(box ref _i) => {},
+        //~^ ERROR switch the order of `ref` and `box`
+        None => {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.rs b/tests/ui/pattern/pattern-bad-ref-box-order.rs
new file mode 100644
index 00000000000..f3fcf0ceacf
--- /dev/null
+++ b/tests/ui/pattern/pattern-bad-ref-box-order.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![feature(box_patterns)]
+#![allow(dead_code)]
+
+fn foo(f: Option<Box<i32>>) {
+    match f {
+        Some(ref box _i) => {},
+        //~^ ERROR switch the order of `ref` and `box`
+        None => {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.stderr b/tests/ui/pattern/pattern-bad-ref-box-order.stderr
new file mode 100644
index 00000000000..a49f05c1028
--- /dev/null
+++ b/tests/ui/pattern/pattern-bad-ref-box-order.stderr
@@ -0,0 +1,8 @@
+error: switch the order of `ref` and `box`
+  --> $DIR/pattern-bad-ref-box-order.rs:8:14
+   |
+LL |         Some(ref box _i) => {},
+   |              ^^^^^^^ help: swap them: `box ref`
+
+error: aborting due to 1 previous error
+