about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_ast_lowering/pat.rs33
-rw-r--r--src/test/ui/issues/issue-72574-1.rs8
-rw-r--r--src/test/ui/issues/issue-72574-1.stderr14
-rw-r--r--src/test/ui/issues/issue-72574-2.rs10
-rw-r--r--src/test/ui/issues/issue-72574-2.stderr14
5 files changed, 76 insertions, 3 deletions
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index 496e401d061..55c1f802663 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode};
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_span::symbol::Ident;
@@ -102,10 +103,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // Note that unlike for slice patterns,
             // where `xs @ ..` is a legal sub-slice pattern,
             // it is not a legal sub-tuple pattern.
-            if pat.is_rest() {
-                rest = Some((idx, pat.span));
-                break;
+            match pat.kind {
+                // Found a sub-tuple rest pattern
+                PatKind::Rest => {
+                    rest = Some((idx, pat.span));
+                    break;
+                }
+                // Found a sub-tuple pattern `$binding_mode $ident @ ..`.
+                // This is not allowed as a sub-tuple pattern
+                PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
+                    rest = Some((idx, pat.span));
+                    let sp = pat.span;
+                    self.diagnostic()
+                        .struct_span_err(
+                            sp,
+                            &format!("`{} @` is not allowed in a {}", ident.name, ctx),
+                        )
+                        .span_label(sp, "this is only allowed in slice patterns")
+                        .help("remove this and bind each tuple field independently")
+                        .span_suggestion_verbose(
+                            sp,
+                            &format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident),
+                            "..".to_string(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    break;
+                }
+                _ => {}
             }
+
             // It was not a sub-tuple pattern so lower it normally.
             elems.push(self.lower_pat(pat));
         }
diff --git a/src/test/ui/issues/issue-72574-1.rs b/src/test/ui/issues/issue-72574-1.rs
new file mode 100644
index 00000000000..efbb0bfb150
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-1.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x = (1, 2, 3);
+    match x {
+        (_a, _x @ ..) => {}
+        _ => {}
+    }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple
diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr
new file mode 100644
index 00000000000..329f7d008d4
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-1.stderr
@@ -0,0 +1,14 @@
+error: `_x @` is not allowed in a tuple
+  --> $DIR/issue-72574-1.rs:4:14
+   |
+LL |         (_a, _x @ ..) => {}
+   |              ^^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of _x, discard the tuple's remaining fields
+   |
+LL |         (_a, ..) => {}
+   |              ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs
new file mode 100644
index 00000000000..0c8f6fcc508
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-2.rs
@@ -0,0 +1,10 @@
+struct Binder(i32, i32, i32);
+
+fn main() {
+    let x = Binder(1, 2, 3);
+    match x {
+        Binder(_a, _x @ ..) => {}
+        _ => {}
+    }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple struct
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
new file mode 100644
index 00000000000..6faa57bcca6
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-2.stderr
@@ -0,0 +1,14 @@
+error: `_x @` is not allowed in a tuple struct
+  --> $DIR/issue-72574-2.rs:6:20
+   |
+LL |         Binder(_a, _x @ ..) => {}
+   |                    ^^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of _x, discard the tuple's remaining fields
+   |
+LL |         Binder(_a, ..) => {}
+   |                    ^^
+
+error: aborting due to previous error
+