about summary refs log tree commit diff
path: root/tests/ui/rfc-1445-restrict-constants-in-patterns
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfc-1445-restrict-constants-in-patterns')
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs26
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs26
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs26
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs26
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs59
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs26
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr8
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs26
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr8
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs29
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr16
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs29
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr16
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs29
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr16
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs29
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr16
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr21
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs39
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr8
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs135
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs19
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr8
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs43
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr25
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs40
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr16
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs21
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr25
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs17
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs23
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr18
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs19
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr8
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs21
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr8
-rw-r--r--tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs53
37 files changed, 978 insertions, 0 deletions
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
new file mode 100644
index 00000000000..1914e155493
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapEmbedded(*const NoDerive);
+
+const WRAP_UNSAFE_EMBEDDED: WrapEmbedded = WrapEmbedded(std::ptr::null());
+
+fn main() {
+    match WRAP_UNSAFE_EMBEDDED {
+        WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
+        _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
new file mode 100644
index 00000000000..e713b003b00
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<X>(*const X);
+
+const WRAP_UNSAFE_PARAM: WrapParam<NoDerive> = WrapParam(std::ptr::null());
+
+fn main() {
+    match WRAP_UNSAFE_PARAM {
+        WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
+        _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
new file mode 100644
index 00000000000..04da14c5419
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapEmbedded(*const NoDerive);
+
+const WRAP_UNSAFE_EMBEDDED: & &WrapEmbedded = & &WrapEmbedded(std::ptr::null());
+
+fn main() {
+    match WRAP_UNSAFE_EMBEDDED {
+        WRAP_UNSAFE_EMBEDDED => { println!("WRAP_UNSAFE_EMBEDDED correctly matched itself"); }
+        _ => { panic!("WRAP_UNSAFE_EMBEDDED did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
new file mode 100644
index 00000000000..8313c25e753
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
@@ -0,0 +1,26 @@
+// Test explores how `#[structral_match]` behaves in tandem with
+// `*const` and `*mut` pointers.
+
+// run-pass
+
+#![warn(pointer_structural_match)]
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive
+// (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<X>(*const X);
+
+const WRAP_UNSAFE_PARAM: & &WrapParam<NoDerive> = & &WrapParam(std::ptr::null());
+
+fn main() {
+    match WRAP_UNSAFE_PARAM {
+        WRAP_UNSAFE_PARAM => { println!("WRAP_UNSAFE_PARAM correctly matched itself"); }
+        _ => { panic!("WRAP_UNSAFE_PARAM did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs
new file mode 100644
index 00000000000..dca8aaef150
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/allow-use-behind-cousin-variant.rs
@@ -0,0 +1,59 @@
+// rust-lang/rust#62614: we want to allow matching on constants of types that
+// have non-structural-match variants, *if* the constant itself does not use
+// any such variant.
+
+// NOTE: for now, deliberately leaving the lint `indirect_structural_match` set
+// to its default, so that we will not issue a diangostic even if
+// rust-lang/rust#62614 remains an open issue.
+
+// 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;
+const SUM_THREE: Eek = Eek::UnusedByTheConst(Sum(3,0));
+
+const EEK_ZERO: &[Eek] = &[];
+const EEK_ONE: &[Eek] = &[THE_CONST];
+
+pub fn main() {
+    match Eek::UnusedByTheConst(Sum(1,2)) {
+        ref sum if sum == &SUM_THREE => { println!("Hello 0"); }
+        _ => { println!("Gbye"); }
+    }
+
+    match Eek::TheConst {
+        THE_CONST => { println!("Hello 1"); }
+        _ => { println!("Gbye"); }
+    }
+
+
+    match & &Eek::TheConst {
+        & & THE_CONST => { println!("Hello 2"); }
+        _ => { println!("Gbye"); }
+    }
+
+    match & & &[][..] {
+        & & EEK_ZERO => { println!("Hello 3"); }
+        & & EEK_ONE => { println!("Gbye"); }
+        _ => { println!("Gbye"); }
+    }
+
+    match & & &[Eek::TheConst][..] {
+        & & EEK_ZERO => { println!("Gby"); }
+        & & EEK_ONE => { println!("Hello 4"); }
+        _ => { println!("Gbye"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
new file mode 100644
index 00000000000..7623839fdd1
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
@@ -0,0 +1,26 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline(NoDerive);
+
+const WRAP_DIRECT_INLINE: WrapInline = WrapInline(NoDerive(0));
+
+fn main() {
+    match WRAP_DIRECT_INLINE {
+        WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
new file mode 100644
index 00000000000..c73a6cf1326
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
+   |
+LL |         WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
new file mode 100644
index 00000000000..93022a23dbf
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.rs
@@ -0,0 +1,26 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+struct NoDerive(i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<T>(T);
+
+const WRAP_DIRECT_PARAM: WrapParam<NoDerive> = WrapParam(NoDerive(0));
+
+fn main() {
+    match WRAP_DIRECT_PARAM {
+        WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
new file mode 100644
index 00000000000..6fdf9db89b8
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-param.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
+   |
+LL |         WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
new file mode 100644
index 00000000000..894739ff705
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline<'a>(&'a &'a NoDerive);
+
+const WRAP_DOUBLY_INDIRECT_INLINE: & &WrapInline = & &WrapInline(& & NoDerive(0));
+
+fn main() {
+    match WRAP_DOUBLY_INDIRECT_INLINE {
+        WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARN this was previously accepted
+        _ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
new file mode 100644
index 00000000000..10dd635ff96
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
@@ -0,0 +1,16 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9
+   |
+LL |         WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
new file mode 100644
index 00000000000..1699dae4624
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<'a, T>(&'a &'a T);
+
+const WRAP_DOUBLY_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(& & NoDerive(0));
+
+fn main() {
+    match WRAP_DOUBLY_INDIRECT_PARAM {
+        WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARN this was previously accepted
+        _ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
new file mode 100644
index 00000000000..66aecbc4f30
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
@@ -0,0 +1,16 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9
+   |
+LL |         WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
new file mode 100644
index 00000000000..2672bdd9e56
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapInline(NoDerive);
+
+const WRAP_INDIRECT_INLINE: & &WrapInline = & &WrapInline(NoDerive(0));
+
+fn main() {
+    match WRAP_INDIRECT_INLINE {
+        WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARN this was previously accepted
+        _ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
new file mode 100644
index 00000000000..ee92954a693
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
@@ -0,0 +1,16 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9
+   |
+LL |         WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
new file mode 100644
index 00000000000..3489995ae71
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
@@ -0,0 +1,29 @@
+// This is part of a set of tests exploring the different ways a
+// structural-match ADT might try to hold a
+// non-structural-match in hidden manner that lets matches
+// through that we had intended to reject.
+//
+// See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
+#![warn(indirect_structural_match)]
+// run-pass
+
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
+
+// This impl makes NoDerive irreflexive.
+impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
+
+impl Eq for NoDerive { }
+
+#[derive(PartialEq, Eq)]
+struct WrapParam<T>(T);
+
+const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
+
+fn main() {
+    match WRAP_INDIRECT_PARAM {
+        WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARN this was previously accepted
+        _ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
new file mode 100644
index 00000000000..f0c492d6a73
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
@@ -0,0 +1,16 @@
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9
+   |
+LL |         WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
new file mode 100644
index 00000000000..bd294047919
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
@@ -0,0 +1,21 @@
+error[E0658]: use of unstable library feature 'structural_match'
+  --> $DIR/feature-gate.rs:29:6
+   |
+LL | impl std::marker::StructuralPartialEq for Foo { }
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
+   = help: add `#![feature(structural_match)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'structural_match'
+  --> $DIR/feature-gate.rs:31:6
+   |
+LL | impl std::marker::StructuralEq for Foo { }
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #31434 <https://github.com/rust-lang/rust/issues/31434> for more information
+   = help: add `#![feature(structural_match)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
new file mode 100644
index 00000000000..ee6674097ce
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
@@ -0,0 +1,39 @@
+// Test that use of structural-match traits is only permitted with a feature gate,
+// and that if a feature gate is supplied, it permits the type to be
+// used in a match.
+
+// revisions: with_gate no_gate
+
+// gate-test-structural_match
+
+#![allow(unused)]
+#![feature(rustc_attrs)]
+#![cfg_attr(with_gate, feature(structural_match))]
+
+
+struct Foo {
+    x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+#[rustc_error]
+fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        _ => { }
+    }
+}
+
+impl std::marker::StructuralPartialEq for Foo { }
+//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+impl std::marker::StructuralEq for Foo { }
+//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+
+impl PartialEq<Foo> for Foo {
+    fn eq(&self, other: &Self) -> bool {
+        self.x == other.x
+    }
+}
+impl Eq for Foo { }
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
new file mode 100644
index 00000000000..623fd585acc
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/feature-gate.with_gate.stderr
@@ -0,0 +1,8 @@
+error: fatal error triggered by #[rustc_error]
+  --> $DIR/feature-gate.rs:21:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
new file mode 100644
index 00000000000..2b3fbd2a4d2
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
@@ -0,0 +1,135 @@
+// run-pass
+
+// This file checks that fn ptrs are considered structurally matchable.
+// See also rust-lang/rust#63479.
+
+fn main() {
+    let mut count = 0;
+
+    // A type which is not structurally matchable:
+    struct NotSM;
+
+    // And one that is:
+    #[derive(PartialEq, Eq)]
+    struct SM;
+
+    fn trivial() {}
+
+    fn sm_to(_: SM) {}
+    fn not_sm_to(_: NotSM) {}
+    fn to_sm() -> SM { SM }
+    fn to_not_sm() -> NotSM { NotSM }
+
+    // To recreate the scenario of interest in #63479, we need to add
+    // a ref-level-of-indirection so that we descend into the type.
+
+    fn r_sm_to(_: &SM) {}
+    fn r_not_sm_to(_: &NotSM) {}
+    fn r_to_r_sm(_: &()) -> &SM { &SM }
+    fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM }
+
+    #[derive(PartialEq, Eq)]
+    struct Wrap<T>(T);
+
+    // In the code below, we put the match input into a local so that
+    // we can assign it an explicit type that is an fn ptr instead of
+    // a singleton type of the fn itself that the type inference would
+    // otherwise assign.
+
+    // Check that fn() is structural-match
+    const CFN1: Wrap<fn()> = Wrap(trivial);
+    let input: Wrap<fn()> = Wrap(trivial);
+    match Wrap(input) {
+        Wrap(CFN1) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(T) is structural-match when T is too.
+    const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
+    let input: Wrap<fn(SM)> = Wrap(sm_to);
+    match Wrap(input) {
+        Wrap(CFN2) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> T is structural-match when T is too.
+    const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
+    let input: Wrap<fn() -> SM> = Wrap(to_sm);
+    match Wrap(input) {
+        Wrap(CFN3) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(T) is structural-match even if T is not.
+    const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+    let input: Wrap<fn(NotSM)> = Wrap(not_sm_to);
+    match Wrap(input) {
+        Wrap(CFN4) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> T is structural-match even if T is not.
+    const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+    let input: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
+    match Wrap(input) {
+        Wrap(CFN5) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(&T) is structural-match when T is too.
+    const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
+    let input: Wrap<fn(&SM)> = Wrap(r_sm_to);
+    match Wrap(input) {
+        Wrap(CFN6) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> &T is structural-match when T is too.
+    const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+    let input: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
+    match Wrap(input) {
+        Wrap(CFN7) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn(T) is structural-match even if T is not.
+    const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+    let input: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
+    match Wrap(input) {
+        Wrap(CFN8) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that fn() -> T is structural-match even if T is not.
+    const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+    let input: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
+    match Wrap(input) {
+        Wrap(CFN9) => count += 1,
+        Wrap(_) => {}
+    };
+
+    // Check that a type which has fn ptrs is structural-match.
+    #[derive(PartialEq, Eq)]
+    struct Foo {
+        alpha: fn(NotSM),
+        beta: fn() -> NotSM,
+        gamma: fn(SM),
+        delta: fn() -> SM,
+    }
+
+    const CFOO: Foo = Foo {
+        alpha: not_sm_to,
+        beta: to_not_sm,
+        gamma: sm_to,
+        delta: to_sm,
+    };
+
+    let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm };
+    match input {
+        CFOO => count += 1,
+        Foo { .. } => {}
+    };
+
+    // Final count must be 10 now if all
+    assert_eq!(count, 10);
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
new file mode 100644
index 00000000000..2a915d61e3d
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs
@@ -0,0 +1,19 @@
+// Issue 61188 pointed out a case where we hit an ICE during code gen:
+// the compiler assumed that `PartialEq` was always implemented on any
+// use of a `const` item in a pattern context, but the pre-existing
+// structural-match checking was too shallow
+// (see rust-lang/rust#62307), and so we hit cases where we were
+// trying to dispatch to `PartialEq` on types that did not implement
+// that trait.
+
+struct B(i32);
+
+const A: &[B] = &[];
+
+pub fn main() {
+    match &[][..] {
+        A => (),
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => (),
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
new file mode 100644
index 00000000000..0bf369fa8cb
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/issue-61188-match-slice-forbidden-without-eq.rs:15:9
+   |
+LL |         A => (),
+   |         ^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
new file mode 100644
index 00000000000..46d8ee3b6be
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
@@ -0,0 +1,43 @@
+// RFC 1445 introduced `#[structural_match]`; this attribute must
+// appear on the `struct`/`enum` definition for any `const` used in a
+// pattern.
+//
+// This is our (forever-unstable) way to mark a datatype as having a
+// `PartialEq` implementation that is equivalent to recursion over its
+// substructure. This avoids (at least in the short term) any need to
+// resolve the question of what semantics is used for such matching.
+// (See RFC 1445 for more details and discussion.)
+
+// Issue 62307 pointed out a case where the structural-match checking
+// was too shallow.
+#![warn(indirect_structural_match, nontrivial_structural_match)]
+// run-pass
+
+#[derive(Debug)]
+struct B(i32);
+
+// Overriding `PartialEq` to use this strange notion of "equality" exposes
+// whether `match` is using structural-equality or method-dispatch
+// under the hood, which is the antithesis of rust-lang/rfcs#1445
+impl PartialEq for B {
+    fn eq(&self, other: &B) -> bool { std::cmp::min(self.0, other.0) == 0 }
+}
+
+fn main() {
+    const RR_B0: & & B = & & B(0);
+    const RR_B1: & & B = & & B(1);
+
+    match RR_B0 {
+        RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARN this was previously accepted
+        _ => { }
+    }
+
+    match RR_B1 {
+        RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+        //~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
+        //~| WARN this was previously accepted
+        _ => { }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
new file mode 100644
index 00000000000..955ab4b548b
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
@@ -0,0 +1,25 @@
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9
+   |
+LL |         RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+   |         ^^^^^
+   |
+   = 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>
+note: the lint level is defined here
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
+   |
+LL | #![warn(indirect_structural_match, nontrivial_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
+   |
+LL |         RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+   |         ^^^^^
+   |
+   = 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: 2 warnings emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs
new file mode 100644
index 00000000000..567685950e9
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs
@@ -0,0 +1,40 @@
+// run-pass
+
+// The actual regression test from #63479. (Including this because my
+// first draft at fn-ptr-is-structurally-matchable.rs failed to actually
+// cover the case this hit; I've since expanded it accordingly, but the
+// experience left me wary of leaving this regression test out.)
+
+#![warn(pointer_structural_match)]
+
+#[derive(Eq)]
+struct A {
+  a: i64
+}
+
+impl PartialEq for A {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.a.eq(&other.a)
+    }
+}
+
+type Fn = fn(&[A]);
+
+fn my_fn(_args: &[A]) {
+  println!("hello world");
+}
+
+const TEST: Fn = my_fn;
+
+struct B(Fn);
+
+fn main() {
+  let s = B(my_fn);
+  match s {
+    B(TEST) => println!("matched"),
+     //~^ WARN pointers in patterns behave unpredictably
+    //~| WARN this was previously accepted by the compiler but is being phased out
+    _ => panic!("didn't match")
+  };
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
new file mode 100644
index 00000000000..d6afc0255ec
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
@@ -0,0 +1,16 @@
+warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-63479-match-fnptr.rs:35:7
+   |
+LL |     B(TEST) => println!("matched"),
+   |       ^^^^
+   |
+   = 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/70861>
+note: the lint level is defined here
+  --> $DIR/issue-63479-match-fnptr.rs:8:9
+   |
+LL | #![warn(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs
new file mode 100644
index 00000000000..0260caa82cb
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.rs
@@ -0,0 +1,21 @@
+// Matching against NaN should result in a warning
+
+#![allow(unused)]
+#![deny(illegal_floating_point_literal_pattern)]
+
+const NAN: f64 = f64::NAN;
+
+fn main() {
+    let x = NAN;
+    match x {
+        NAN => {}, //~ ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+
+    match [x, 1.0] {
+        [NAN, _] => {}, //~ ERROR floating-point types cannot be used
+        //~| WARN this was previously accepted by the compiler but is being phased out
+        _ => {},
+    };
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
new file mode 100644
index 00000000000..f37255d0828
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
@@ -0,0 +1,25 @@
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:11:9
+   |
+LL |         NAN => {},
+   |         ^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+note: the lint level is defined here
+  --> $DIR/issue-6804.rs:4:9
+   |
+LL | #![deny(illegal_floating_point_literal_pattern)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-6804.rs:17:10
+   |
+LL |         [NAN, _] => {},
+   |          ^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs
new file mode 100644
index 00000000000..7ba0f3a9e8d
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-empty-array-allowed-without-eq-issue-62336.rs
@@ -0,0 +1,17 @@
+// Pre-existing behavior has been to reject patterns with consts
+// denoting non-empty arrays of non-`Eq` types, but *accept* empty
+// arrays of such types.
+//
+// See rust-lang/rust#62336.
+
+// run-pass
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+fn main() {
+    const FOO: [B; 0] = [];
+    match [] {
+        FOO => { }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs
new file mode 100644
index 00000000000..59a22c33778
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.rs
@@ -0,0 +1,23 @@
+#[derive(PartialEq)]
+struct Foo {
+    x: u32
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => { }
+    }
+
+    let x = 0.0;
+    match x {
+        f32::INFINITY => { }
+        //~^ WARNING floating-point types cannot be used in patterns
+        //~| WARNING this was previously accepted by the compiler but is being phased out
+        _ => { }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
new file mode 100644
index 00000000000..616ed9e484b
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
@@ -0,0 +1,18 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-forbidden-without-eq.rs:11:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-forbidden-without-eq.rs:18:9
+   |
+LL |         f32::INFINITY => { }
+   |         ^^^^^^^^^^^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs
new file mode 100644
index 00000000000..151a475c919
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.rs
@@ -0,0 +1,19 @@
+// Issue 62307 pointed out a case where the structural-match checking
+// was too shallow.
+//
+// Here we check similar behavior for non-empty arrays of types that
+// do not derive `Eq`.
+//
+// (Current behavior for empty arrays differs and thus is not tested
+// here; see rust-lang/rust#62336.)
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+fn main() {
+    const FOO: [B; 1] = [B(0)];
+    match [B(1)] {
+        FOO => { }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr
new file mode 100644
index 00000000000..371f8a0aa1d
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-nonempty-array-forbidden-without-eq.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
new file mode 100644
index 00000000000..a8deb8a7550
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs
@@ -0,0 +1,21 @@
+#[derive(Eq)]
+struct Foo {
+    x: u32
+}
+
+impl PartialEq for Foo {
+    fn eq(&self, _: &Foo) -> bool {
+        false // ha ha!
+    }
+}
+
+const FOO: Foo = Foo { x: 0 };
+
+fn main() {
+    let y = Foo { x: 1 };
+    match y {
+        FOO => { }
+        //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+        _ => { }
+    }
+}
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
new file mode 100644
index 00000000000..4157cf65283
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
+   |
+LL |         FOO => { }
+   |         ^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs b/tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs
new file mode 100644
index 00000000000..50f91420ce2
--- /dev/null
+++ b/tests/ui/rfc-1445-restrict-constants-in-patterns/phantom-data-is-structurally-matchable.rs
@@ -0,0 +1,53 @@
+// run-pass
+
+// This file checks that `PhantomData` is considered structurally matchable.
+
+use std::marker::PhantomData;
+
+fn main() {
+    let mut count = 0;
+
+    // A type which is not structurally matchable:
+    struct NotSM;
+
+    // And one that is:
+    #[derive(PartialEq, Eq)]
+    struct SM;
+
+    // Check that SM is structural-match:
+    const CSM: SM = SM;
+    match SM {
+        CSM => count += 1,
+    };
+
+    // Check that PhantomData<T> is structural-match even if T is not.
+    const CPD1: PhantomData<NotSM> = PhantomData;
+    match PhantomData {
+        CPD1 => count += 1,
+    };
+
+    // Check that PhantomData<T> is structural-match when T is.
+    const CPD2: PhantomData<SM> = PhantomData;
+    match PhantomData {
+        CPD2 => count += 1,
+    };
+
+    // Check that a type which has a PhantomData is structural-match.
+    #[derive(PartialEq, Eq, Default)]
+    struct Foo {
+        alpha: PhantomData<NotSM>,
+        beta: PhantomData<SM>,
+    }
+
+    const CFOO: Foo = Foo {
+        alpha: PhantomData,
+        beta: PhantomData,
+    };
+
+    match Foo::default() {
+        CFOO => count += 1,
+    };
+
+    // Final count must be 4 now if all
+    assert_eq!(count, 4);
+}