2019-09-13 15:08:01 +00:00
|
|
|
// 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.
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn() is structural-match
|
2019-09-13 15:08:01 +00:00
|
|
|
const CFN1: Wrap<fn()> = Wrap(trivial);
|
|
|
|
let input: Wrap<fn()> = Wrap(trivial);
|
|
|
|
match Wrap(input) {
|
|
|
|
Wrap(CFN1) => count += 1,
|
|
|
|
Wrap(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn(T) is structural-match when T is too.
|
2019-09-13 15:08:01 +00:00
|
|
|
const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
|
|
|
|
let input: Wrap<fn(SM)> = Wrap(sm_to);
|
|
|
|
match Wrap(input) {
|
|
|
|
Wrap(CFN2) => count += 1,
|
|
|
|
Wrap(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn() -> T is structural-match when T is too.
|
2019-09-13 15:08:01 +00:00
|
|
|
const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
|
|
|
|
let input: Wrap<fn() -> SM> = Wrap(to_sm);
|
|
|
|
match Wrap(input) {
|
|
|
|
Wrap(CFN3) => count += 1,
|
|
|
|
Wrap(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn(T) is structural-match even if T is not.
|
2019-09-13 15:08:01 +00:00
|
|
|
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(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn() -> T is structural-match even if T is not.
|
2019-09-13 15:08:01 +00:00
|
|
|
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(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn(&T) is structural-match when T is too.
|
2019-09-13 15:08:01 +00:00
|
|
|
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(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn() -> &T is structural-match when T is too.
|
2019-09-13 15:08:01 +00:00
|
|
|
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(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn(T) is structural-match even if T is not.
|
2019-09-13 15:08:01 +00:00
|
|
|
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(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that fn() -> T is structural-match even if T is not.
|
2019-09-13 15:08:01 +00:00
|
|
|
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(_) => {}
|
|
|
|
};
|
|
|
|
|
2020-03-24 18:52:22 +00:00
|
|
|
// Check that a type which has fn ptrs is structural-match.
|
2019-09-13 15:08:01 +00:00
|
|
|
#[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);
|
|
|
|
}
|