pub macro assert_is_covariant {
(for[$($gen_params:tt)*] ($type_name:ty) over $lf:lifetime where {$a:lifetime, $b:lifetime} [$($where_body:tt)*] [$($where_body1:tt)*] [$($where_body2:tt)*]) => {
#[allow(dead_code, unused)]
const _: () = {
struct Cov<$lf, $($gen_params)*>($type_name) where $($where_body)*;
fn test_cov<$a: $b, $b, $($gen_params)*>(
subtype: *const Cov<$a, $($gen_params)*>,
mut _supertype: *const Cov<$b, $($gen_params)*>,
) where $($where_body1)*, $($where_body2)* {
_supertype = subtype;
}
};
},
(for[$($gen_params:tt)*] ($type_name:ty) over $lf:lifetime $(where [$($where_body:tt)*])?) => {
#[allow(dead_code, unused)]
const _: () = {
struct Cov<$lf, $($gen_params)*>($type_name) $(where $($where_body)*)?;
fn test_cov<'__a: '__b, '__b, $($gen_params)*>(
subtype: *const Cov<'__a, $($gen_params)*>,
mut _supertype: *const Cov<'__b, $($gen_params)*>,
) $(where $($where_body)*)? {
_supertype = subtype;
}
};
},
(for[$($($gen_params:tt)+)?] ($type_name:ty) over $type_param:ident) => {
#[allow(dead_code, unused)]
const _: () = {
type Transform<$($($gen_params)+,)? $type_param> = $type_name;
assert_is_covariant!{
for[$($($gen_params)+)?] (Transform<$($($gen_params)+,)? &'__a ()>) over '__a
}
};
},
(($type_name:ty) over $($rest:tt)*) => {
assert_is_covariant!(for[] ($type_name) over $($rest)*);
}
}
pub macro assert_is_contravariant {
(for[$($gen_params:tt)*] ($type_name:ty) over $lf:lifetime $(where [$($where_body:tt)*])?) => {
#[allow(dead_code, unused)]
const _: () = {
struct Contra<$lf, $($gen_params)*>($type_name) $(where $($where_body)*)?;
fn test_contra<'__a: '__b, '__b, $($gen_params)*>(
mut _subtype: *const Contra<'__a, $($gen_params)*>,
supertype: *const Contra<'__b, $($gen_params)*>,
) $(where $($where_body)*)? {
_subtype = supertype;
}
};
},
(for[$($($gen_params:tt)+)?] ($type_name:ty) over $type_param:ident) => {
#[allow(dead_code, unused)]
const _: () = {
type Transform<$($($gen_params)+,)? $type_param> = $type_name;
assert_is_contravariant!{
for[$($($gen_params)+)?] (Transform<$($($gen_params)+,)? &'__a ()>) over '__a
}
};
},
(($type_name:ty) over $($rest:tt)*) => {
assert_is_contravariant!(for[] ($type_name) over $($rest)*);
}
}