summaryrefslogtreecommitdiffstats
path: root/tests/ui/rfc-1445-restrict-constants-in-patterns
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/rfc-1445-restrict-constants-in-patterns
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
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 000000000..1914e1554
--- /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 000000000..e713b003b
--- /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 000000000..04da14c54
--- /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 000000000..8313c25e7
--- /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 000000000..dca8aaef1
--- /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 000000000..7623839fd
--- /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 000000000..c73a6cf13
--- /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 000000000..93022a23d
--- /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 000000000..6fdf9db89
--- /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 000000000..894739ff7
--- /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 000000000..10dd635ff
--- /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 000000000..1699dae46
--- /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 000000000..66aecbc4f
--- /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 000000000..2672bdd9e
--- /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 000000000..ee92954a6
--- /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 000000000..3489995ae
--- /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 000000000..f0c492d6a
--- /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 000000000..bd2940479
--- /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 000000000..ee6674097
--- /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 000000000..623fd585a
--- /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 000000000..2b3fbd2a4
--- /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 000000000..2a915d61e
--- /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 000000000..0bf369fa8
--- /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 000000000..46d8ee3b6
--- /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 000000000..955ab4b54
--- /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 000000000..567685950
--- /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 000000000..d6afc0255
--- /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 000000000..0260caa82
--- /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 000000000..f37255d08
--- /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 000000000..7ba0f3a9e
--- /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 000000000..59a22c337
--- /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 000000000..616ed9e48
--- /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 000000000..151a475c9
--- /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 000000000..371f8a0aa
--- /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 000000000..a8deb8a75
--- /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 000000000..4157cf652
--- /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 000000000..50f91420c
--- /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);
+}