3 // Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions,
4 // which "says that a destructor applied to an object built from a constructor
5 // behaves as expected". -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction
7 // It's a little more complicated here, because of pointers and regions and
8 // trying to get assert failure messages that at least identify which case
11 enum E<T> { Thing(isize, T), #[allow(unused_tuple_struct_fields)] Nothing((), ((), ()), [i8; 0]) }
13 fn is_none(&self) -> bool {
15 E::Thing(..) => false,
16 E::Nothing(..) => true
19 fn get_ref(&self) -> (isize, &T) {
21 E::Nothing(..) => panic!("E::get_ref(Nothing::<{}>)", stringify!(T)),
22 E::Thing(x, ref y) => (x, y)
27 macro_rules! check_option {
28 ($e:expr, $T:ty) => {{
29 check_option!($e, $T, |ptr| assert_eq!(*ptr, $e));
31 ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{
32 assert!(None::<$T>.is_none());
34 let s_ = Some::<$T>(e);
35 let $v = s_.as_ref().unwrap();
40 macro_rules! check_fancy {
41 ($e:expr, $T:ty) => {{
42 check_fancy!($e, $T, |ptr| assert_eq!(*ptr, $e));
44 ($e:expr, $T:ty, |$v:ident| $chk:expr) => {{
45 assert!(E::Nothing::<$T>((), ((), ()), [23; 0]).is_none());
47 let t_ = E::Thing::<$T>(23, e);
50 _ => panic!("Thing::<{}>(23, {}).get_ref() != (23, _)",
51 stringify!($T), stringify!($e))
56 macro_rules! check_type {
58 check_option!($($a)*);
64 check_type!(&17, &isize);
65 check_type!(Box::new(18), Box<isize>);
66 check_type!("foo".to_string(), String);
67 check_type!(vec![20, 22], Vec<isize>);
68 check_type!(main, fn(), |pthing| {
69 assert_eq!(main as fn(), *pthing as fn())