1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
//@ 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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
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, //~WARN behave unpredictably
//~| previously accepted
Foo { .. } => {}
};
// Final count must be 10 now if all
assert_eq!(count, 10);
}
|