typewit/
type_eq_ne_guts.rs

1// $type_cmp is either TypeEq or TypeNe
2macro_rules! declare_zip_helper {($_:tt $type_cmp_ty:ident) => {
3    macro_rules! zip_impl {
4        // Using more specific patterns for $L and $R to prevent usage of macros,
5        // which can expand to different values on each use
6        ($_( $type_cmp:ident [$_($L:ident)::*, $_($R:ident)::*] ),* $_(,)*) => {
7            $_(
8                let _te: $type_cmp_ty<$_($L)::*, $_($R)::*> = $type_cmp;
9            )*
10
11            // SAFETY: 
12            // `$type_cmp_ty<$_($L)::*, $_($R)::*>` for every passed `$type_cmp`
13            // implies `$type_cmp_ty<(L0, L1, ...), (R0, R1, ...)>`
14            unsafe {
15                $type_cmp_ty::<($_($_($L)::*,)*), ($_($_($R)::*,)*)>::new_unchecked()
16            }
17        }
18    }
19
20}} pub(crate) use declare_zip_helper;
21
22// $type_cmp is either TypeEq or TypeNe
23macro_rules! declare_helpers {($_:tt $type_cmp_ty:ident $tyfn:ident $callfn:ident) => {
24    macro_rules! projected_type_cmp {
25        ($type_cmp:expr, $L:ty, $R:ty, $F:ty) => ({
26            // Safety(TypeEq): 
27            // this takes a `TypeEq<$L, $R>`,
28            // which implies `TypeEq<CallFn<$tyfn, $L>, CallFn<$tyfn, $R>>`.
29            //
30            // Safety(TypeNe): 
31            // this takes a `TypeNe<$L, $R>`,
32            // and requires `$tyfn: InjTypeFn<$L> + InjTypeFn<$R>`,
33            // (`InjTypeFn` guarantees that unequal arguments map to unequal return values),
34            // which implies `TypeNe<CallInjFn<$tyfn, $L>, CallInjFn<$tyfn, $R>>`.
35            unsafe {
36                __ProjectVars::<$F, $L, $R> {
37                    te: $type_cmp,
38                    projected_te: $type_cmp_ty::new_unchecked(),
39                }.projected_te
40            }
41        })
42    } use projected_type_cmp;
43
44    struct __ProjectVars<F, L: ?Sized, R: ?Sized> 
45    where
46        InvokeAlias<F>: $tyfn<L> + $tyfn<R>
47    {
48        #[allow(dead_code)]
49        te: $type_cmp_ty<L, R>,
50
51        //         $type_cmp_ty<L, R> 
52        // implies $type_cmp_ty<$callfn<F, L>, $callfn<F, R>>
53        projected_te: $type_cmp_ty<$callfn<InvokeAlias<F>, L>, $callfn<InvokeAlias<F>, R>>,
54    }
55
56    macro_rules! unprojected_type_cmp {
57        ($type_cmp:expr, $L:ty, $R:ty, $F:ty) => ({
58            // safety: 
59            // This macro takes a `$type_cmp_ty<$L, $R>` value,
60            // which implies `$type_cmp_ty<UncallFn<F, $L>, UncallFn<F, $R>>`
61            //  
62            // The properties section of RevTypeFn guarantees this for 
63            // both TypeEq and TypeNe
64            unsafe {
65                __UnprojectVars::<$F, $L, $R> {
66                    te: $type_cmp,
67                    unprojected_te: $type_cmp_ty::new_unchecked(),
68                }.unprojected_te
69            }
70        })
71    }
72
73    struct __UnprojectVars<F, L: ?Sized, R: ?Sized> 
74    where
75        InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
76    {
77        #[allow(dead_code)]
78        te: $type_cmp_ty<L, R>,
79
80        //         $type_cmp_ty<L, R> 
81        // implies $type_cmp_ty<UncallFn<F, L>, UncallFn<F, R>>
82        //  
83        // The properties section of RevTypeFn guarantees this for 
84        // both TypeEq and TypeNe
85        unprojected_te: $type_cmp_ty<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>,
86    }
87
88}} pub(crate) use declare_helpers;
89