diff options
Diffstat (limited to 'tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs')
-rw-r--r-- | tests/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs | 135 |
1 files changed, 135 insertions, 0 deletions
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); +} |