]> git.lizzy.rs Git - rust.git/blob - src/test/ui/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs
Rollup merge of #97317 - GuillaumeGomez:gui-settings-text-click, r=jsha
[rust.git] / src / test / ui / rfc-1445-restrict-constants-in-patterns / fn-ptr-is-structurally-matchable.rs
1 // run-pass
2
3 // This file checks that fn ptrs are considered structurally matchable.
4 // See also rust-lang/rust#63479.
5
6 fn main() {
7     let mut count = 0;
8
9     // A type which is not structurally matchable:
10     struct NotSM;
11
12     // And one that is:
13     #[derive(PartialEq, Eq)]
14     struct SM;
15
16     fn trivial() {}
17
18     fn sm_to(_: SM) {}
19     fn not_sm_to(_: NotSM) {}
20     fn to_sm() -> SM { SM }
21     fn to_not_sm() -> NotSM { NotSM }
22
23     // To recreate the scenario of interest in #63479, we need to add
24     // a ref-level-of-indirection so that we descend into the type.
25
26     fn r_sm_to(_: &SM) {}
27     fn r_not_sm_to(_: &NotSM) {}
28     fn r_to_r_sm(_: &()) -> &SM { &SM }
29     fn r_to_r_not_sm(_: &()) -> &NotSM { &NotSM }
30
31     #[derive(PartialEq, Eq)]
32     struct Wrap<T>(T);
33
34     // In the code below, we put the match input into a local so that
35     // we can assign it an explicit type that is an fn ptr instead of
36     // a singleton type of the fn itself that the type inference would
37     // otherwise assign.
38
39     // Check that fn() is structural-match
40     const CFN1: Wrap<fn()> = Wrap(trivial);
41     let input: Wrap<fn()> = Wrap(trivial);
42     match Wrap(input) {
43         Wrap(CFN1) => count += 1,
44         Wrap(_) => {}
45     };
46
47     // Check that fn(T) is structural-match when T is too.
48     const CFN2: Wrap<fn(SM)> = Wrap(sm_to);
49     let input: Wrap<fn(SM)> = Wrap(sm_to);
50     match Wrap(input) {
51         Wrap(CFN2) => count += 1,
52         Wrap(_) => {}
53     };
54
55     // Check that fn() -> T is structural-match when T is too.
56     const CFN3: Wrap<fn() -> SM> = Wrap(to_sm);
57     let input: Wrap<fn() -> SM> = Wrap(to_sm);
58     match Wrap(input) {
59         Wrap(CFN3) => count += 1,
60         Wrap(_) => {}
61     };
62
63     // Check that fn(T) is structural-match even if T is not.
64     const CFN4: Wrap<fn(NotSM)> = Wrap(not_sm_to);
65     let input: Wrap<fn(NotSM)> = Wrap(not_sm_to);
66     match Wrap(input) {
67         Wrap(CFN4) => count += 1,
68         Wrap(_) => {}
69     };
70
71     // Check that fn() -> T is structural-match even if T is not.
72     const CFN5: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
73     let input: Wrap<fn() -> NotSM> = Wrap(to_not_sm);
74     match Wrap(input) {
75         Wrap(CFN5) => count += 1,
76         Wrap(_) => {}
77     };
78
79     // Check that fn(&T) is structural-match when T is too.
80     const CFN6: Wrap<fn(&SM)> = Wrap(r_sm_to);
81     let input: Wrap<fn(&SM)> = Wrap(r_sm_to);
82     match Wrap(input) {
83         Wrap(CFN6) => count += 1,
84         Wrap(_) => {}
85     };
86
87     // Check that fn() -> &T is structural-match when T is too.
88     const CFN7: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
89     let input: Wrap<fn(&()) -> &SM> = Wrap(r_to_r_sm);
90     match Wrap(input) {
91         Wrap(CFN7) => count += 1,
92         Wrap(_) => {}
93     };
94
95     // Check that fn(T) is structural-match even if T is not.
96     const CFN8: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
97     let input: Wrap<fn(&NotSM)> = Wrap(r_not_sm_to);
98     match Wrap(input) {
99         Wrap(CFN8) => count += 1,
100         Wrap(_) => {}
101     };
102
103     // Check that fn() -> T is structural-match even if T is not.
104     const CFN9: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
105     let input: Wrap<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm);
106     match Wrap(input) {
107         Wrap(CFN9) => count += 1,
108         Wrap(_) => {}
109     };
110
111     // Check that a type which has fn ptrs is structural-match.
112     #[derive(PartialEq, Eq)]
113     struct Foo {
114         alpha: fn(NotSM),
115         beta: fn() -> NotSM,
116         gamma: fn(SM),
117         delta: fn() -> SM,
118     }
119
120     const CFOO: Foo = Foo {
121         alpha: not_sm_to,
122         beta: to_not_sm,
123         gamma: sm_to,
124         delta: to_sm,
125     };
126
127     let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm };
128     match input {
129         CFOO => count += 1,
130         Foo { .. } => {}
131     };
132
133     // Final count must be 10 now if all
134     assert_eq!(count, 10);
135 }