pub enum TypeCmp<L: ?Sized, R: ?Sized> {
Eq(TypeEq<L, R>),
Ne(TypeNe<L, R>),
}
Expand description
The result of comparing two types for equality.
§Example
§Custom array creation
(this example requires Rust 1.63.0, because of core::array::from_fn
).
use typewit::{const_marker::Usize, TypeCmp, TypeEq, TypeNe};
let empty: [String; 0] = [];
assert_eq!(ArrayMaker::<String, 0>::empty().make(), empty);
assert_eq!(ArrayMaker::<u8, 2>::defaulted().make(), [0u8, 0u8]);
assert_eq!(ArrayMaker::with(|i| i.pow(2)).make(), [0usize, 1, 4, 9]);
enum ArrayMaker<T, const LEN: usize> {
NonEmpty(fn(usize) -> T, TypeNe<[T; LEN], [T; 0]>),
Empty(TypeEq<[T; LEN], [T; 0]>),
}
impl<T, const LEN: usize> ArrayMaker<T, LEN> {
pub fn make(self) -> [T; LEN] {
match self {
ArrayMaker::NonEmpty(func, _) => std::array::from_fn(func),
ArrayMaker::Empty(te) => te.to_left([]),
}
}
pub const fn defaulted() -> Self
where
T: Default
{
Self::with(|_| Default::default())
}
pub const fn with(func: fn(usize) -> T) -> Self {
match Usize::<LEN>.equals(Usize::<0>) // : TypeCmp<Usize<LEN>, Usize<0>>
.project::<ArrayFn<T>>() // : TypeCmp<[T; LEN], [T; 0]>
{
TypeCmp::Ne(ne) => ArrayMaker::NonEmpty(func, ne),
TypeCmp::Eq(eq) => ArrayMaker::Empty(eq),
}
}
}
impl<T> ArrayMaker<T, 0> {
pub const fn empty() -> Self {
Self::Empty(TypeEq::NEW)
}
}
impl<T, const LEN: usize> Copy for ArrayMaker<T, LEN> {}
impl<T, const LEN: usize> Clone for ArrayMaker<T, LEN> {
fn clone(&self) -> Self { *self }
}
typewit::inj_type_fn! {
// Declares `struct ArrayFn`, which implements `InjTypeFn<Usize<LEN>>`:
// an injective type-level function from `Usize<LEN>` to `[T; LEN]`
struct ArrayFn<T>;
impl<const LEN: usize> Usize<LEN> => [T; LEN]
}
Variants§
Implementations§
Source§impl<L: ?Sized, R: ?Sized> TypeCmp<L, R>
impl<L: ?Sized, R: ?Sized> TypeCmp<L, R>
Sourcepub fn with_any() -> Self
👎Deprecated: fallout of https://github.com/rust-lang/rust/issues/97156
,TypeId::of::<L>() != TypeId::of::<R>()
does not imply L != R
pub fn with_any() -> Self
https://github.com/rust-lang/rust/issues/97156
,TypeId::of::<L>() != TypeId::of::<R>()
does not imply L != R
Constructs a TypeCmp<L, R>
by comparing the L
and R
types for equality.
§Example
use typewit::TypeCmp;
let eq: TypeCmp<u8, u8> = TypeCmp::with_any();
assert!(matches!(eq, TypeCmp::Eq(_)));
let ne = TypeCmp::<u8, i8>::with_any();
assert!(matches!(ne, TypeCmp::Ne(_)));
Sourcepub const fn flip(self) -> TypeCmp<R, L>
pub const fn flip(self) -> TypeCmp<R, L>
Swaps the type arguments of this TypeCmp
§Example
use typewit::{TypeCmp, type_ne};
const TC: TypeCmp<u8, i8> = TypeCmp::Ne(type_ne!(u8, i8));
const TK: TypeCmp<i8, u8> = TC.flip();
Sourcepub const fn join_left<Q: ?Sized>(self, left: TypeEq<Q, L>) -> TypeCmp<Q, R>
pub const fn join_left<Q: ?Sized>(self, left: TypeEq<Q, L>) -> TypeCmp<Q, R>
Joins this TypeCmp<L, R>
with a TypeEq<Q, L>
, producing a TypeCmp<Q, R>
.
§Example
use typewit::{TypeCmp, TypeEq, type_ne};
const TC: TypeCmp<str, [u8]> = type_ne!(str, [u8]).to_cmp();
const fn foo<A: ?Sized>(eq: TypeEq<A, str>) {
let _tc: TypeCmp<A, [u8]> = TC.join_left(eq);
}
Sourcepub const fn join_right<Q: ?Sized>(self, right: TypeEq<R, Q>) -> TypeCmp<L, Q>
pub const fn join_right<Q: ?Sized>(self, right: TypeEq<R, Q>) -> TypeCmp<L, Q>
Joins this TypeCmp<L, R>
with a TypeEq<R, Q>
, producing a TypeCmp<L, Q>
.
§Example
use typewit::{TypeCmp, TypeEq, type_ne};
const NE: TypeCmp<String, Vec<u8>> = type_ne!(String, Vec<u8>).to_cmp();
const fn foo<A>(eq: TypeEq<Vec<u8>, A>) {
let _ne: TypeCmp<String, A> = NE.join_right(eq);
}
Sourcepub const fn eq(self) -> Option<TypeEq<L, R>>
pub const fn eq(self) -> Option<TypeEq<L, R>>
Converts this TypeCmp<L, R>
into an Option<TypeEq<L, R>>
.
§Example
use typewit::{TypeCmp, TypeEq, type_ne};
let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
assert!(matches!(eq.eq(), Some(TypeEq::<u8, u8>{..})));
let ne = TypeCmp::Ne(type_ne!(u8, i8));
assert!(matches!(ne.eq(), None::<TypeEq<u8, i8>>));
Sourcepub const fn ne(self) -> Option<TypeNe<L, R>>
pub const fn ne(self) -> Option<TypeNe<L, R>>
Converts this TypeCmp<L, R>
into an Option<TypeNe<L, R>>
.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
assert!(matches!(eq.ne(), None::<TypeNe<u8, u8>>));
let ne = TypeCmp::Ne(type_ne!(u8, i8));
assert!(matches!(ne.ne(), Some(TypeNe::<u8, i8>{..})));
Sourcepub const fn is_eq(self) -> bool
pub const fn is_eq(self) -> bool
Returns whether this TypeCmp
is a TypeCmp::Eq
.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
assert_eq!(EQ.is_eq(), true);
const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
assert_eq!(NE.is_eq(), false);
Sourcepub const fn is_ne(self) -> bool
pub const fn is_ne(self) -> bool
Returns whether this TypeCmp
is a TypeCmp::Ne
.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
assert_eq!(EQ.is_ne(), false);
const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
assert_eq!(NE.is_ne(), true);
Source§impl<L, R> TypeCmp<L, R>
impl<L, R> TypeCmp<L, R>
Sourcepub const fn zip<A>(self, other: A) -> TypeCmp<(L, A::L), (R, A::R)>where
A: BaseTypeWitness,
pub const fn zip<A>(self, other: A) -> TypeCmp<(L, A::L), (R, A::R)>where
A: BaseTypeWitness,
Combines this TypeCmp<L, R>
with a BaseTypeWitness
type to produce a
TypeCmp<(L, A::L), (R, A::R)>
.
§Alternative
methods::zip2
is an alternative to this function.
This method always returns TypeCmp
,
while that function
returns TypeNe
when any argument is a TypeNe
.
§Returned variant
This returns either TypeCmp::Eq
or TypeCmp::Ne
depending on the arguments:
- if all arguments (including
self
) areTypeEq
orTypeCmp::Eq
, this returnsTypeCmp::Eq
- if any argument (including
self
) is aTypeNe
orTypeCmp::Ne
, this returnsTypeCmp::Ne
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
const EQ: TypeEq<u16, u16> = TypeEq::NEW;
const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
assert!(matches!(
TC_EQ.zip(NE),
TypeCmp::<(i64, u8), (i64, i8)>::Ne(_),
));
assert!(matches!(
TC_EQ.zip(EQ),
TypeCmp::<(i64, u16), (i64, u16)>::Eq(_),
));
assert!(matches!(
TC_EQ.zip(TC_EQ),
TypeCmp::<(i64, i64), (i64, i64)>::Eq(_),
));
assert!(matches!(
TC_EQ.zip(TC_NE),
TypeCmp::<(i64, u32), (i64, u64)>::Ne(_),
));
Sourcepub const fn zip3<A, B>(
self,
arg0: A,
arg1: B,
) -> TypeCmp<(L, A::L, B::L), (R, A::R, B::R)>
pub const fn zip3<A, B>( self, arg0: A, arg1: B, ) -> TypeCmp<(L, A::L, B::L), (R, A::R, B::R)>
Combines this TypeCmp<L, R>
with two BaseTypeWitness
types to produce a
TypeCmp<(L, A::L, B::L), (R, A::R, B::R)>
.
§Alternative
methods::zip3
is an alternative to this function.
This method always returns TypeCmp
,
while that function
returns TypeNe
when any argument is a TypeNe
.
§Returned variant
This returns either TypeCmp::Eq
or TypeCmp::Ne
depending on the arguments:
- if all arguments (including
self
) areTypeEq
orTypeCmp::Eq
, this returnsTypeCmp::Eq
- if any argument (including
self
) is aTypeNe
orTypeCmp::Ne
, this returnsTypeCmp::Ne
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
const EQ: TypeEq<u16, u16> = TypeEq::NEW;
const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
assert!(matches!(
TC_EQ.zip3(EQ, NE),
TypeCmp::<(i64, u16, u8), (i64, u16, i8)>::Ne(_),
));
assert!(matches!(
TC_EQ.zip3(EQ, TC_EQ),
TypeCmp::<(i64, u16, i64), (i64, u16, i64)>::Eq(_),
));
assert!(matches!(
TC_EQ.zip3(NE, TC_NE),
TypeCmp::<(i64, u8, u32), (i64, i8, u64)>::Ne(_),
));
Sourcepub const fn zip4<A, B, C>(
self,
arg0: A,
arg1: B,
arg2: C,
) -> TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>where
A: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B: BaseTypeWitness,
B::L: Sized,
B::R: Sized,
C: BaseTypeWitness,
pub const fn zip4<A, B, C>(
self,
arg0: A,
arg1: B,
arg2: C,
) -> TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>where
A: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B: BaseTypeWitness,
B::L: Sized,
B::R: Sized,
C: BaseTypeWitness,
Combines this TypeCmp<L, R>
with three BaseTypeWitness
types to produce a
TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>
.
§Alternative
methods::zip4
is an alternative to this function.
This method always returns TypeCmp
,
while that function
returns TypeNe
when any argument is a TypeNe
.
§Returned variant
This returns either TypeCmp::Eq
or TypeCmp::Ne
depending on the arguments:
- if all arguments (including
self
) areTypeEq
orTypeCmp::Eq
, this returnsTypeCmp::Eq
- if any argument (including
self
) is aTypeNe
orTypeCmp::Ne
, this returnsTypeCmp::Ne
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
const EQ: TypeEq<u16, u16> = TypeEq::NEW;
const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
assert!(matches!(
TC_EQ.zip4(EQ, NE, TC_NE),
TypeCmp::<(i64, u16, u8, u32), (i64, u16, i8, u64)>::Ne(_),
));
assert!(matches!(
TC_EQ.zip4(EQ, TC_EQ, EQ),
TypeCmp::<(i64, u16, i64, u16), (i64, u16, i64, u16)>::Eq(_),
));
§impl<L: ?Sized, R: ?Sized> TypeCmp<L, R>
impl<L: ?Sized, R: ?Sized> TypeCmp<L, R>
pub const fn map<F>(
self: TypeCmp<L, R>,
func: F,
) -> TypeCmp<CallInjFn<F, L>, CallInjFn<F, R>>
pub const fn map<F>( self: TypeCmp<L, R>, func: F, ) -> TypeCmp<CallInjFn<F, L>, CallInjFn<F, R>>
Maps the type arguments of this TypeCmp
by using the F
injective type-level function.
Use this function over project
if you want the type of the passed in function to be inferred.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
use std::num::Wrapping;
const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
assert!(matches!(EQ.map(WrappingFn), TypeCmp::<Wrapping<u8>, Wrapping<u8>>::Eq(_)));
const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
assert!(matches!(NE.map(WrappingFn), TypeCmp::<Wrapping<i8>, Wrapping<u8>>::Ne(_)));
inj_type_fn!{
struct WrappingFn;
impl<T> T => Wrapping<T>
}
pub const fn project<F>(
self: TypeCmp<L, R>,
) -> TypeCmp<CallInjFn<F, L>, CallInjFn<F, R>>
pub const fn project<F>( self: TypeCmp<L, R>, ) -> TypeCmp<CallInjFn<F, L>, CallInjFn<F, R>>
Maps the type arguments of this TypeCmp
by using the F
injective type-level function.
Use this function over map
if you want to specify the type of the passed in function explicitly.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
use std::mem::ManuallyDrop as ManDrop;
const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
assert!(matches!(EQ.project::<ManDropFn>(), TypeCmp::<ManDrop<u8>, ManDrop<u8>>::Eq(_)));
const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
assert!(matches!(NE.project::<ManDropFn>(), TypeCmp::<ManDrop<i8>, ManDrop<u8>>::Ne(_)));
inj_type_fn!{
struct ManDropFn;
impl<T> T => ManDrop<T>
}
pub const fn unmap<F>(self, func: F) -> TypeCmp<UncallFn<F, L>, UncallFn<F, R>>
pub const fn unmap<F>(self, func: F) -> TypeCmp<UncallFn<F, L>, UncallFn<F, R>>
Maps the type arguments of this TypeCmp
by using the reversed
version of the F
type-level function.
Use this function over unproject
if you want the type of the passed in function to be inferred.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
use std::num::Wrapping;
const EQ: TypeCmp<Wrapping<u8>, Wrapping<u8>> = TypeEq::NEW.to_cmp();
assert!(matches!(EQ.unmap(WrappingFn), TypeCmp::<u8, u8>::Eq(_)));
const NE: TypeCmp<Wrapping<i8>, Wrapping<u8>> =
type_ne!(Wrapping<i8>, Wrapping<u8>).to_cmp();
assert!(matches!(NE.unmap(WrappingFn), TypeCmp::<i8, u8>::Ne(_)));
inj_type_fn!{
struct WrappingFn;
impl<T> T => Wrapping<T>
}
pub const fn unproject<F>(self) -> TypeCmp<UncallFn<F, L>, UncallFn<F, R>>
pub const fn unproject<F>(self) -> TypeCmp<UncallFn<F, L>, UncallFn<F, R>>
Maps the type arguments of this TypeCmp
by using the reversed
version of the F
type-level function.
Use this function over unmap
if you want to specify the type of the passed in function explicitly.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
use std::mem::MaybeUninit as MaybeUn;
const EQ: TypeCmp<MaybeUn<u8>, MaybeUn<u8>> = TypeEq::NEW.to_cmp();
assert!(matches!(EQ.unproject::<MaybeUnFn>(), TypeCmp::<u8, u8>::Eq(_)));
const NE: TypeCmp<MaybeUn<i8>, MaybeUn<u8>> =
type_ne!(MaybeUn<i8>, MaybeUn<u8>).to_cmp();
assert!(matches!(NE.unproject::<MaybeUnFn>(), TypeCmp::<i8, u8>::Ne(_)));
inj_type_fn!{
struct MaybeUnFn;
impl<T> T => MaybeUn<T>
}
pub const fn in_ref<'a>(self) -> TypeCmp<&'a L, &'a R>
pub const fn in_ref<'a>(self) -> TypeCmp<&'a L, &'a R>
Converts a TypeCmp<L, R>
to TypeCmp<&L, &R>
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
assert!(matches!(EQ.in_ref(), TypeCmp::<&u8, &u8>::Eq(_)));
const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
assert!(matches!(NE.in_ref(), TypeCmp::<&i8, &u8>::Ne(_)));
pub fn in_mut<'a>(self) -> TypeCmp<&'a mut L, &'a mut R>
pub fn in_mut<'a>(self) -> TypeCmp<&'a mut L, &'a mut R>
Converts a TypeCmp<L, R>
to TypeCmp<&mut L, &mut R>
§Constness
This requires the "rust_1_83"
crate feature to be a const fn
.
§Example
use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
assert!(matches!(EQ.in_mut(), TypeCmp::<&mut u8, &mut u8>::Eq(_)));
const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
assert!(matches!(NE.in_mut(), TypeCmp::<&mut i8, &mut u8>::Ne(_)));
§impl<L, R> TypeCmp<L, R>
impl<L, R> TypeCmp<L, R>
pub const fn in_array<O, const UL: usize, const UR: usize>(
self,
other: O,
) -> TypeCmp<[L; UL], [R; UR]>
pub const fn in_array<O, const UL: usize, const UR: usize>( self, other: O, ) -> TypeCmp<[L; UL], [R; UR]>
Combines TypeCmp<L, R>
and a
O:
BaseTypeWitness
<L = Usize<UL>, R = Usize<UR>>
into TypeCmp<[L; UL], [R; UR]>
§Alternative
methods::in_array
is an alternative to this function.
This method always returns TypeCmp
,
while that function
returns TypeNe
when any argument is a TypeNe
.
§Returned variant
This returns either TypeCmp::Eq
or TypeCmp::Ne
depending on the arguments:
- if all arguments (including
self
) areTypeEq
orTypeCmp::Eq
, this returnsTypeCmp::Eq
- if any argument (including
self
) is aTypeNe
orTypeCmp::Ne
, this returnsTypeCmp::Ne
§Example
§Basic
use typewit::{
const_marker::Usize,
TypeCmp, TypeEq, TypeNe,
type_ne,
};
let cmp_eq_ty: TypeCmp<i32, i32> = TypeCmp::Eq(TypeEq::NEW);
let cmp_ne_ty: TypeCmp<i64, u64> = TypeCmp::Ne(type_ne!(i64, u64));
let eq_len: TypeEq<Usize<0>, Usize<0>> = TypeEq::NEW;
let ne_len: TypeNe<Usize<1>, Usize<2>> = Usize.equals(Usize).unwrap_ne();
let cmp_eq_len: TypeCmp<Usize<3>, Usize<3>> = Usize.equals(Usize);
let cmp_ne_len: TypeCmp<Usize<5>, Usize<8>> = Usize.equals(Usize);
assert!(matches!(cmp_eq_ty.in_array(eq_len), TypeCmp::<[i32; 0], [i32; 0]>::Eq(_)));
assert!(matches!(cmp_eq_ty.in_array(ne_len), TypeCmp::<[i32; 1], [i32; 2]>::Ne(_)));
assert!(matches!(cmp_eq_ty.in_array(cmp_eq_len), TypeCmp::<[i32; 3], [i32; 3]>::Eq(_)));
assert!(matches!(cmp_eq_ty.in_array(cmp_ne_len), TypeCmp::<[i32; 5], [i32; 8]>::Ne(_)));
assert!(matches!(cmp_ne_ty.in_array(eq_len), TypeCmp::<[i64; 0], [u64; 0]>::Ne(_)));
assert!(matches!(cmp_ne_ty.in_array(ne_len), TypeCmp::<[i64; 1], [u64; 2]>::Ne(_)));
assert!(matches!(cmp_ne_ty.in_array(cmp_eq_len), TypeCmp::<[i64; 3], [u64; 3]>::Ne(_)));
assert!(matches!(cmp_ne_ty.in_array(cmp_ne_len), TypeCmp::<[i64; 5], [u64; 8]>::Ne(_)));