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