about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan MacKenzie <ecstaticmorse@gmail.com>2020-03-16 21:01:05 -0700
committerDylan MacKenzie <ecstaticmorse@gmail.com>2020-04-28 14:58:50 -0700
commit66f2d44c737134d36778956f1b1c928a3b36cb87 (patch)
tree43a6cfa64bdd4dc3bd1a5e59109ce5d23bbe62dd
parent796c0ca5548de6d4a5220dbae500e00db616243b (diff)
downloadrust-66f2d44c737134d36778956f1b1c928a3b36cb87.tar.gz
rust-66f2d44c737134d36778956f1b1c928a3b36cb87.zip
Add tests from #67088 and the issues mentioned in its description
-rw-r--r--src/test/ui/consts/const_in_pattern/accept_structural.rs66
-rw-r--r--src/test/ui/consts/const_in_pattern/issue-62614.rs24
-rw-r--r--src/test/ui/consts/const_in_pattern/issue-65466.rs19
-rw-r--r--src/test/ui/consts/const_in_pattern/issue-65466.stderr15
-rw-r--r--src/test/ui/consts/const_in_pattern/reject_non_partial_eq.rs32
-rw-r--r--src/test/ui/consts/const_in_pattern/reject_non_partial_eq.stderr8
-rw-r--r--src/test/ui/consts/const_in_pattern/reject_non_structural.rs93
-rw-r--r--src/test/ui/consts/const_in_pattern/reject_non_structural.stderr136
-rw-r--r--src/test/ui/consts/const_in_pattern/warn_corner_cases.rs41
-rw-r--r--src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr34
-rw-r--r--src/test/ui/issues/issue-55511.rs2
-rw-r--r--src/test/ui/issues/issue-55511.stderr14
12 files changed, 468 insertions, 16 deletions
diff --git a/src/test/ui/consts/const_in_pattern/accept_structural.rs b/src/test/ui/consts/const_in_pattern/accept_structural.rs
new file mode 100644
index 00000000000..70ec95faf6a
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/accept_structural.rs
@@ -0,0 +1,66 @@
+// run-pass
+
+#![warn(indirect_structural_match)]
+
+// This test is checking our logic for structural match checking by enumerating
+// the different kinds of const expressions. This test is collecting cases where
+// we have accepted the const expression as a pattern in the past and wish to
+// continue doing so.
+//
+// Even if a non-structural-match type is part of an expression in a const's
+// definition, that does not necessarily disqualify the const from being a match
+// pattern: in principle, we just need the types involved in the final value to
+// be structurally matchable.
+
+// See also RFC 1445
+
+#![feature(type_ascription)]
+
+#[derive(Copy, Clone, Debug)]
+struct NoPartialEq(u32);
+
+#[derive(Copy, Clone, Debug)]
+struct NoDerive(u32);
+
+// This impl makes `NoDerive` irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+impl Eq for NoDerive { }
+
+type OND = Option<NoDerive>;
+
+fn main() {
+    const FIELD1: u32 = NoPartialEq(1).0;
+    match 1 { FIELD1 => dbg!(FIELD1), _ => panic!("whoops"), };
+    const FIELD2: u32 = NoDerive(1).0;
+    match 1 { FIELD2 => dbg!(FIELD2), _ => panic!("whoops"), };
+
+    enum CLike { One = 1, #[allow(dead_code)] Two = 2, }
+    const ONE_CAST: u32 = CLike::One as u32;
+    match 1 { ONE_CAST => dbg!(ONE_CAST), _ => panic!("whoops"), };
+
+    const NO_DERIVE_NONE: OND = None;
+    const INDIRECT: OND = NO_DERIVE_NONE;
+    match None { INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
+
+    const TUPLE: (OND, OND) = (None, None);
+    match (None, None) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
+
+    const TYPE: OND = None: OND;
+    match None { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
+
+    const ARRAY: [OND; 2] = [None, None];
+    match [None; 2] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
+
+    const REPEAT: [OND; 2] = [None; 2];
+    match [None, None] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
+
+    trait Trait: Sized { const ASSOC: Option<Self>; }
+    impl Trait for NoDerive { const ASSOC: Option<NoDerive> = None; }
+    match None { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
+
+    const BLOCK: OND = { NoDerive(10); None };
+    match None { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
+
+    const ADDR_OF: &OND = &None;
+    match &None { ADDR_OF => dbg!(ADDR_OF),  _ => panic!("whoops"), };
+}
diff --git a/src/test/ui/consts/const_in_pattern/issue-62614.rs b/src/test/ui/consts/const_in_pattern/issue-62614.rs
new file mode 100644
index 00000000000..4ea9a283618
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/issue-62614.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+struct Sum(u32, u32);
+
+impl PartialEq for Sum {
+    fn eq(&self, other: &Self) -> bool { self.0 + self.1 == other.0 + other.1 }
+}
+
+impl Eq for Sum { }
+
+#[derive(PartialEq, Eq)]
+enum Eek {
+    TheConst,
+    UnusedByTheConst(Sum)
+}
+
+const THE_CONST: Eek = Eek::TheConst;
+
+pub fn main() {
+    match Eek::UnusedByTheConst(Sum(1,2)) {
+        THE_CONST => { panic!(); }
+        _ => {}
+    }
+}
diff --git a/src/test/ui/consts/const_in_pattern/issue-65466.rs b/src/test/ui/consts/const_in_pattern/issue-65466.rs
new file mode 100644
index 00000000000..e974fd9397d
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/issue-65466.rs
@@ -0,0 +1,19 @@
+#![deny(indirect_structural_match)]
+
+#[derive(PartialEq, Eq)]
+enum O<T> {
+    Some(*const T), // Can also use PhantomData<T>
+    None,
+}
+
+struct B;
+
+const C: &[O<B>] = &[O::None];
+
+fn main() {
+    let x = O::None;
+    match &[x][..] {
+        C => (),
+        _ => (),
+    }
+}
diff --git a/src/test/ui/consts/const_in_pattern/issue-65466.stderr b/src/test/ui/consts/const_in_pattern/issue-65466.stderr
new file mode 100644
index 00000000000..9fe3049d1d8
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/issue-65466.stderr
@@ -0,0 +1,15 @@
+error[E0601]: `main` function not found in crate `issue_65466`
+  --> $DIR/issue-65466.rs:1:1
+   |
+LL | / #![deny(indirect_structural_match)]
+LL | |
+LL | | #[derive(PartialEq, Eq)]
+LL | | enum O<T> {
+...  |
+LL | |     }
+LL | | }
+   | |_^ consider adding a `main` function to `$DIR/issue-65466.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/consts/const_in_pattern/reject_non_partial_eq.rs b/src/test/ui/consts/const_in_pattern/reject_non_partial_eq.rs
new file mode 100644
index 00000000000..a8216901c02
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/reject_non_partial_eq.rs
@@ -0,0 +1,32 @@
+// This test is illustrating the difference between how failing to derive
+// `PartialEq` is handled compared to failing to implement it at all.
+
+// See also RFC 1445
+
+#[derive(PartialEq, Eq)]
+struct Structural(u32);
+
+struct NoPartialEq(u32);
+
+struct NoDerive(u32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+const NO_DERIVE_NONE: Option<NoDerive> = None;
+const NO_PARTIAL_EQ_NONE: Option<NoPartialEq> = None;
+
+fn main() {
+    match None {
+        NO_DERIVE_NONE => println!("NO_DERIVE_NONE"),
+        _ => panic!("whoops"),
+    }
+
+    match None {
+        NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => panic!("whoops"),
+    }
+}
diff --git a/src/test/ui/consts/const_in_pattern/reject_non_partial_eq.stderr b/src/test/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
new file mode 100644
index 00000000000..95cfa4a9ebe
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/reject_non_partial_eq.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `NoPartialEq` in a pattern, `NoPartialEq` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_partial_eq.rs:28:9
+   |
+LL |         NO_PARTIAL_EQ_NONE => println!("NO_PARTIAL_EQ_NONE"),
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const_in_pattern/reject_non_structural.rs b/src/test/ui/consts/const_in_pattern/reject_non_structural.rs
new file mode 100644
index 00000000000..c39163ee278
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/reject_non_structural.rs
@@ -0,0 +1,93 @@
+// This test of structural match checking enumerates the different kinds of
+// const definitions, collecting cases where the const pattern is rejected.
+//
+// Note: Even if a non-structural-match type is part of an expression in a
+// const's definition, that does not necessarily disqualify the const from being
+// a match pattern: in principle, we just need the types involved in the final
+// value to be structurally matchable.
+
+// See also RFC 1445
+
+#![feature(type_ascription)]
+#![warn(indirect_structural_match)]
+//~^ NOTE lint level is defined here
+
+#[derive(Copy, Clone, Debug)]
+struct NoPartialEq;
+
+#[derive(Copy, Clone, Debug)]
+struct NoDerive;
+
+// This impl makes `NoDerive` irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+type OND = Option<NoDerive>;
+
+struct TrivialEq(OND);
+
+// This impl makes `TrivialEq` trivial.
+impl PartialEq for TrivialEq { fn eq(&self, _: &Self) -> bool { true } }
+
+impl Eq for TrivialEq { }
+
+fn main() {
+    #[derive(PartialEq, Eq, Debug)]
+    enum Derive<X> { Some(X), None, }
+
+    const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
+    match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const FIELD: OND = TrivialEq(Some(NoDerive)).0;
+    match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const NO_DERIVE_SOME: OND = Some(NoDerive);
+    const INDIRECT: OND = NO_DERIVE_SOME;
+    match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const TUPLE: (OND, OND) = (None, Some(NoDerive));
+    match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const TYPE: OND = Some(NoDerive): OND;
+    match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const ARRAY: [OND; 2] = [None, Some(NoDerive)];
+    match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const REPEAT: [OND; 2] = [Some(NoDerive); 2];
+    match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    trait Trait: Sized { const ASSOC: Option<Self>; }
+    impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
+    match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const BLOCK: OND = { NoDerive; Some(NoDerive) };
+    match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
+    //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+
+    const ADDR_OF: &OND = &Some(NoDerive);
+    match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
+    //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| WARN previously accepted by the compiler but is being phased out
+    //~| NOTE for more information, see issue #62411
+}
diff --git a/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr b/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr
new file mode 100644
index 00000000000..8ea28e259ab
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr
@@ -0,0 +1,136 @@
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:40:36
+   |
+LL |     match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
+   |                                    ^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:45:28
+   |
+LL |     match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
+   |                            ^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:51:27
+   |
+LL |     match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
+   |                           ^^^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:56:36
+   |
+LL |     match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
+   |                                    ^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:61:28
+   |
+LL |     match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
+   |                            ^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:66:36
+   |
+LL |     match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
+   |                                    ^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:71:33
+   |
+LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
+   |                                 ^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:71:33
+   |
+LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
+   |                                 ^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:79:28
+   |
+LL |     match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
+   |                            ^^^^^^^^^^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:84:28
+   |
+LL |     match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
+   |                            ^^^^^
+
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:89:29
+   |
+LL |     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
+   |                             ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/reject_non_structural.rs:12:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:40:36
+   |
+LL |     match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
+   |                                    ^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:45:28
+   |
+LL |     match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
+   |                            ^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:51:27
+   |
+LL |     match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
+   |                           ^^^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:56:36
+   |
+LL |     match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
+   |                                    ^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:61:28
+   |
+LL |     match Some(NoDerive) { TYPE => dbg!(TYPE), _ => panic!("whoops"), };
+   |                            ^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:66:36
+   |
+LL |     match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
+   |                                    ^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:71:33
+   |
+LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
+   |                                 ^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:71:33
+   |
+LL |     match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
+   |                                 ^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:79:28
+   |
+LL |     match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
+   |                            ^^^^^^^^^^^^^^^
+
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/reject_non_structural.rs:84:28
+   |
+LL |     match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
+   |                            ^^^^^
+
+error: aborting due to 20 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs b/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
new file mode 100644
index 00000000000..c6b794de195
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
@@ -0,0 +1,41 @@
+// run-pass
+
+// This test is checking our logic for structural match checking by enumerating
+// the different kinds of const expressions. This test is collecting cases where
+// we have accepted the const expression as a pattern in the past but we want
+// to begin warning the user that a future version of Rust may start rejecting
+// such const expressions.
+
+// The specific corner cases we are exploring here are instances where the
+// const-evaluator computes a value that *does* meet the conditions for
+// structural-match, but the const expression itself has abstractions (like
+// calls to const functions) that may fit better with a type-based analysis
+// rather than a committment to a specific value.
+
+#![warn(indirect_structural_match)]
+
+#[derive(Copy, Clone, Debug)]
+struct NoDerive(u32);
+
+// This impl makes `NoDerive` irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+impl Eq for NoDerive { }
+
+fn main() {
+    const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
+    match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
+    //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| WARN this was previously accepted
+
+    const fn build() -> Option<NoDerive> { None }
+    const CALL: Option<NoDerive> = build();
+    match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
+    //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| WARN this was previously accepted
+
+    impl NoDerive { const fn none() -> Option<NoDerive> { None } }
+    const METHOD_CALL: Option<NoDerive> = NoDerive::none();
+    match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
+    //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+    //~| WARN this was previously accepted
+}
diff --git a/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr b/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr
new file mode 100644
index 00000000000..3e7ed573c74
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr
@@ -0,0 +1,34 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/warn_corner_cases.rs:26:47
+   |
+LL |     match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
+   |                                               ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/warn_corner_cases.rs:15:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/warn_corner_cases.rs:32:47
+   |
+LL |     match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
+   |                                               ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/warn_corner_cases.rs:38:47
+   |
+LL |     match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
+   |                                               ^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/issues/issue-55511.rs b/src/test/ui/issues/issue-55511.rs
index 055886bf367..7dfa9c7bcdf 100644
--- a/src/test/ui/issues/issue-55511.rs
+++ b/src/test/ui/issues/issue-55511.rs
@@ -14,8 +14,6 @@ fn main() {
     //~^ ERROR `a` does not live long enough [E0597]
     match b {
         <() as Foo<'static>>::C => { }
-        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
-        //~| WARN will become a hard error in a future release
         _ => { }
     }
 }
diff --git a/src/test/ui/issues/issue-55511.stderr b/src/test/ui/issues/issue-55511.stderr
index d526ddb78e9..b29ff3f7420 100644
--- a/src/test/ui/issues/issue-55511.stderr
+++ b/src/test/ui/issues/issue-55511.stderr
@@ -1,17 +1,3 @@
-warning: to use a constant of type `std::cell::Cell` in a pattern, `std::cell::Cell` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/issue-55511.rs:16:9
-   |
-LL |         <() as Foo<'static>>::C => { }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-55511.rs:1:9
-   |
-LL | #![warn(indirect_structural_match)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
-
 error[E0597]: `a` does not live long enough
   --> $DIR/issue-55511.rs:13:28
    |