From 223674a824317284b42ba197be43fd68b957ab58 Mon Sep 17 00:00:00 2001
From: bohan <bohan-zhang@foxmail.com>
Date: Sun, 15 Oct 2023 19:20:06 +0800
Subject: [PATCH] use `PatKind::error` when an ADT const value has violation

---
 .../rustc_mir_build/src/thir/pattern/const_to_pat.rs  |  8 ++++++++
 tests/ui/pattern/issue-115599.rs                      |  7 +++++++
 tests/ui/pattern/issue-115599.stderr                  | 11 +++++++++++
 3 files changed, 26 insertions(+)
 create mode 100644 tests/ui/pattern/issue-115599.rs
 create mode 100644 tests/ui/pattern/issue-115599.stderr

diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 32d389c4354c7..cda10d9d4304a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -198,6 +198,14 @@ impl<'tcx> ConstToPat<'tcx> {
                     // We errored. Signal that in the pattern, so that follow up errors can be silenced.
                     let kind = PatKind::Error(e);
                     return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
+                } else if let ty::Adt(..) = cv.ty().kind() && matches!(cv, mir::Const::Val(..)) {
+                    // This branch is only entered when the current `cv` is `mir::Const::Val`.
+                    // This is because `mir::Const::ty` has already been handled by `Self::recur`
+                    // and the invalid types may be ignored.
+                    let err = TypeNotStructural { span: self.span, non_sm_ty };
+                    let e = self.tcx().sess.emit_err(err);
+                    let kind = PatKind::Error(e);
+                    return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
                 } else if !self.saw_const_match_lint.get() {
                     if let Some(mir_structural_match_violation) = mir_structural_match_violation {
                         match non_sm_ty.kind() {
diff --git a/tests/ui/pattern/issue-115599.rs b/tests/ui/pattern/issue-115599.rs
new file mode 100644
index 0000000000000..7a222b90aec97
--- /dev/null
+++ b/tests/ui/pattern/issue-115599.rs
@@ -0,0 +1,7 @@
+const CONST_STRING: String = String::new();
+
+fn main() {
+    let empty_str = String::from("");
+    if let CONST_STRING = empty_str {}
+    //~^ ERROR to use a constant of type `Vec<u8>` in a pattern, `Vec<u8>` must be annotated with `#[derive(PartialEq, Eq)]`
+}
diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr
new file mode 100644
index 0000000000000..e6cb6c1ddac77
--- /dev/null
+++ b/tests/ui/pattern/issue-115599.stderr
@@ -0,0 +1,11 @@
+error: to use a constant of type `Vec<u8>` in a pattern, `Vec<u8>` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/issue-115599.rs:5:12
+   |
+LL |     if let CONST_STRING = empty_str {}
+   |            ^^^^^^^^^^^^
+   |
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
+
+error: aborting due to previous error
+