| // This file checks that fn ptrs are *not* considered structurally matchable. | 
 | // See also rust-lang/rust#63479 and RFC 3535. | 
 |  | 
 | 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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         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, //~ERROR behave unpredictably | 
 |         Foo { .. } => {} | 
 |     }; | 
 |  | 
 |     // Final count must be 10 now if all | 
 |     assert_eq!(count, 10); | 
 | } |