summaryrefslogtreecommitdiffstats
path: root/src/test/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
new file mode 100644
index 000000000..2b3fbd2a4
--- /dev/null
+++ b/src/test/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);
+}