pub struct TypeNe<L: ?Sized, R: ?Sized>(/* private fields */);
Expand description
Value-level proof that L
is a different type to R
The opposite of TypeEq
.
§Example
use typewit::{const_marker::Usize, TypeNe};
assert_eq!(
array_ref_chunks(&[3, 5, 8, 13, 21, 34, 55], AssertNotZero::V),
Chunks {chunks: vec![&[3, 5, 8], &[13, 21, 34]], tail: &[55]}
);
fn array_ref_chunks<T, const LEN: usize>(
slice: &[T],
_not_zero: TypeNe<Usize<LEN>, Usize<0>>,
) -> Chunks<'_, T, LEN> {
let mut chunks = slice.chunks_exact(LEN);
Chunks {
chunks: chunks.by_ref().map(|c| <&[T; LEN]>::try_from(c).unwrap()).collect(),
tail: chunks.remainder(),
}
}
#[derive(Debug, PartialEq, Eq)]
struct Chunks<'a, T, const LEN: usize> {
chunks: Vec<&'a [T; LEN]>,
tail: &'a [T],
}
struct AssertNotZero<const N: usize>;
impl<const N: usize> AssertNotZero<N> {
const V: TypeNe<Usize<N>, Usize<0>> = Usize::<N>.equals(Usize::<0>).unwrap_ne();
}
If you attempt to pass 0
as the length of the array chunks,
you’ll get this compile-time error:
error[E0080]: evaluation of `main::_doctest_main_src_type_ne_rs_41_0::AssertNotZero::<0>::V` failed
--> src/type_ne.rs:71:43
|
33 | const V: TypeNe<Usize<N>, Usize<0>> = Usize::<N>.equals(Usize::<0>).unwrap_ne();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `TypeCmp::unwrap_ne` on a `TypeEq` value', src/type_ne.rs:33:73
error[E0080]: erroneous constant used
--> src/type_ne.rs:45:50
|
7 | array_ref_chunks(&[3, 5, 8, 13, 21, 34, 55], AssertNotZero::<0>::V),
| ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
Implementations§
Source§impl<L: ?Sized, R: ?Sized> TypeNe<L, R>
impl<L: ?Sized, R: ?Sized> TypeNe<L, R>
Sourcepub const unsafe fn new_unchecked() -> TypeNe<L, R>
pub const unsafe fn new_unchecked() -> TypeNe<L, R>
Source§impl TypeNe<(), ()>
impl TypeNe<(), ()>
Sourcepub const fn with_fn<F>(
_func: F,
) -> TypeNe<CallInjFn<F, LeftArg>, CallInjFn<F, RightArg>>
pub const fn with_fn<F>( _func: F, ) -> TypeNe<CallInjFn<F, LeftArg>, CallInjFn<F, RightArg>>
Constructs a TypeNe
by mapping from a
TypeNe<
LeftArg
,
RightArg
>
with an injective type-level function.
§Alternative
The type_ne
macro can be used as syntactic sugar
for calling this constructor with a one-off type-level function.
§Example
use typewit::type_ne::{TypeNe, LeftArg, RightArg};
const NE: TypeNe<Option<String>, Vec<u16>> = TypeNe::with_fn(MakeNe::NEW);
typewit::inj_type_fn! {
struct MakeNe<T, U>;
impl LeftArg => Option<T>;
impl RightArg => Vec<U>;
}
Source§impl<L: ?Sized, R: ?Sized> TypeNe<L, R>
impl<L: ?Sized, R: ?Sized> TypeNe<L, R>
Sourcepub fn with_any() -> Option<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() -> Option<Self>
https://github.com/rust-lang/rust/issues/97156
,TypeId::of::<L>() != TypeId::of::<R>()
does not imply L != R
Constructs TypeNe<L, R>
if L != R
, otherwise returns None.
§Example
use typewit::TypeNe;
let _ne: TypeNe<u8, i8> = TypeNe::with_any().unwrap();
assert!(TypeNe::<u8, u8>::with_any().is_none());
Sourcepub const fn flip(self: TypeNe<L, R>) -> TypeNe<R, L>
pub const fn flip(self: TypeNe<L, R>) -> TypeNe<R, L>
Swaps the type arguments of this TypeNe
§Example
use typewit::{TypeNe, type_ne};
const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
const N3: TypeNe<i8, u8> = NE.flip();
Sourcepub const fn join_left<J: ?Sized>(
self: TypeNe<L, R>,
_eq: TypeEq<J, L>,
) -> TypeNe<J, R>
pub const fn join_left<J: ?Sized>( self: TypeNe<L, R>, _eq: TypeEq<J, L>, ) -> TypeNe<J, R>
Joins a proof of L != R
with a proof of J == L
,
creating a proof of J != R
.
§Example
use typewit::{TypeEq, TypeNe, type_ne};
const NE: TypeNe<str, [u8]> = type_ne!(str, [u8]);
const fn foo<A: ?Sized>(eq: TypeEq<A, str>) {
let _ne: TypeNe<A, [u8]> = NE.join_left(eq);
}
Sourcepub const fn join_right<J: ?Sized>(
self: TypeNe<L, R>,
_eq: TypeEq<R, J>,
) -> TypeNe<L, J>
pub const fn join_right<J: ?Sized>( self: TypeNe<L, R>, _eq: TypeEq<R, J>, ) -> TypeNe<L, J>
Joins a proof of L != R
with a proof of R == J
,
creating a proof of L != J
.
§Example
use typewit::{TypeEq, TypeNe, type_ne};
const NE: TypeNe<String, Vec<u8>> = type_ne!(String, Vec<u8>);
const fn foo<A>(eq: TypeEq<Vec<u8>, A>) {
let _ne: TypeNe<String, A> = NE.join_right(eq);
}
Source§impl<L, R> TypeNe<L, R>
impl<L, R> TypeNe<L, R>
Sourcepub const fn zip<A>(
self: TypeNe<L, R>,
other: A,
) -> TypeNe<(L, A::L), (R, A::R)>where
A: BaseTypeWitness,
pub const fn zip<A>(
self: TypeNe<L, R>,
other: A,
) -> TypeNe<(L, A::L), (R, A::R)>where
A: BaseTypeWitness,
Combines this TypeNe<L, R>
with an
A: BaseTypeWitness
to produce a
TypeNe<(L, A::L), (R, A::R)>
.
§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: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
let _: TypeNe<(u8, i8), (i8, u8)> = NE.zip(NE.flip());
let _: TypeNe<(u8, u16), (i8, u16)> = NE.zip(EQ);
let _: TypeNe<(u8, u32), (i8, u64)> = NE.zip(TC);
Sourcepub const fn zip3<A, B>(
self: TypeNe<L, R>,
other1: A,
other2: B,
) -> TypeNe<(L, A::L, B::L), (R, A::R, B::R)>
pub const fn zip3<A, B>( self: TypeNe<L, R>, other1: A, other2: B, ) -> TypeNe<(L, A::L, B::L), (R, A::R, B::R)>
Combines this TypeNe<L, R>
with
two BaseTypeWitness
es to produce a
TypeNe<(L, A::L, B::L), (R, A::R, B::R)>
.
§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: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
let _: TypeNe<(u8, i8, u8), (i8, u8, i8)> = NE.zip3(NE.flip(), NE);
let _: TypeNe<(u8, u16, u16), (i8, u16, u16)> = NE.zip3(EQ, EQ.flip());
let _: TypeNe<(u8, u32, u64), (i8, u64, u32)> = NE.zip3(TC, TC.flip());
Sourcepub const fn zip4<A, B, C>(
self: TypeNe<L, R>,
other1: A,
other2: B,
other3: C,
) -> TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>where
A: BaseTypeWitness,
B: BaseTypeWitness,
C: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B::L: Sized,
B::R: Sized,
pub const fn zip4<A, B, C>(
self: TypeNe<L, R>,
other1: A,
other2: B,
other3: C,
) -> TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>where
A: BaseTypeWitness,
B: BaseTypeWitness,
C: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B::L: Sized,
B::R: Sized,
Combines this TypeNe<L, R>
with
three BaseTypeWitness
es to produce a
TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>
.
§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: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
let _: TypeNe<(u8, i8, u8, i8), (i8, u8, i8, u8)> = NE.zip4(NE.flip(), NE, NE.flip());
let _: TypeNe<(u8, u16, u16, u16), (i8, u16, u16, u16)> = NE.zip4(EQ, EQ.flip(), EQ);
let _: TypeNe<(u8, u32, u64, u32), (i8, u64, u32, u64)> = NE.zip4(TC, TC.flip(), TC);
§impl<L: ?Sized, R: ?Sized> TypeNe<L, R>
impl<L: ?Sized, R: ?Sized> TypeNe<L, R>
pub const fn map<F>(
self: TypeNe<L, R>,
_func: F,
) -> TypeNe<CallInjFn<F, L>, CallInjFn<F, R>>
pub const fn map<F>( self: TypeNe<L, R>, _func: F, ) -> TypeNe<CallInjFn<F, L>, CallInjFn<F, R>>
Maps the type arguments of this TypeNe
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::{TypeNe, inj_type_fn, type_ne};
const NE: TypeNe<u8, u16> = type_ne!(u8, u16);
const N3: TypeNe<[u8; 0], [u16; 0]> = NE.map(ArrayFn::NEW);
inj_type_fn!{
struct ArrayFn<const LEN: usize>;
impl<T> T => [T; LEN]
}
pub const fn project<F>(
self: TypeNe<L, R>,
) -> TypeNe<CallInjFn<F, L>, CallInjFn<F, R>>
pub const fn project<F>( self: TypeNe<L, R>, ) -> TypeNe<CallInjFn<F, L>, CallInjFn<F, R>>
Maps the type arguments of this TypeNe
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::{TypeNe, inj_type_fn, type_ne};
const NE: TypeNe<u8, u16> = type_ne!(u8, u16);
const N3: TypeNe<Vec<u8>, Vec<u16>> = NE.project::<VecFn>();
inj_type_fn!{
struct VecFn;
impl<T> T => Vec<T>
}
pub const fn unmap<F>(self, func: F) -> TypeNe<UncallFn<F, L>, UncallFn<F, R>>
pub const fn unmap<F>(self, func: F) -> TypeNe<UncallFn<F, L>, UncallFn<F, R>>
Maps the type arguments of this TypeNe
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::{TypeNe, inj_type_fn, type_ne};
use std::cmp::Ordering as CmpOrdering;
use std::sync::atomic::Ordering as MemOrdering;
const NE: TypeNe<[CmpOrdering], [MemOrdering]> = type_ne!([CmpOrdering], [MemOrdering]);
const N3: TypeNe<CmpOrdering, MemOrdering> = NE.unmap(SliceFn);
inj_type_fn!{
struct SliceFn;
impl<T> T => [T]
}
pub const fn unproject<F>(self) -> TypeNe<UncallFn<F, L>, UncallFn<F, R>>
pub const fn unproject<F>(self) -> TypeNe<UncallFn<F, L>, UncallFn<F, R>>
Maps the type arguments of this TypeNe
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::{TypeNe, inj_type_fn, type_ne};
const NE: TypeNe<Option<()>, Option<bool>> = type_ne!(Option<()>, Option<bool>);
const N3: TypeNe<(), bool> = NE.unproject::<OptionFn>();
inj_type_fn!{
struct OptionFn;
impl<T> T => Option<T>
}
pub const fn in_ref<'a>(self) -> TypeNe<&'a L, &'a R>
pub const fn in_ref<'a>(self) -> TypeNe<&'a L, &'a R>
Converts a TypeNe<L, R>
to TypeNe<&L, &R>
§Example
use typewit::{TypeNe, inj_type_fn, type_ne};
const NE: TypeNe<i32, u32> = type_ne!(i32, u32);
let foo: i32 = 3;
let bar: u32 = 5;
baz(&foo, &bar, NE.in_ref());
const fn baz<'a, T, U>(foo: &'a T, bar: &'a U, _ne: TypeNe<&'a T, &'a U>) {
// stuff
}
pub fn in_mut<'a>(self) -> TypeNe<&'a mut L, &'a mut R>
pub fn in_mut<'a>(self) -> TypeNe<&'a mut L, &'a mut R>
Converts a TypeNe<L, R>
to TypeNe<&mut L, &mut R>
§Constness
This requires the "rust_1_83"
feature to be a const fn
.
§Example
use typewit::{TypeNe, inj_type_fn, type_ne};
const NE: TypeNe<String, Vec<u8>> = type_ne!(String, Vec<u8>);
let mut foo: String = "hello".to_string();
let mut bar: Vec<u8> = vec![3, 5, 8];
baz(&mut foo, &mut bar, NE.in_mut());
fn baz<'a, T, U>(foo: &'a mut T, bar: &'a mut U, _ne: TypeNe<&'a mut T, &'a mut U>) {
// stuff
}
§impl<L: Sized, R: Sized> TypeNe<L, R>
impl<L: Sized, R: Sized> TypeNe<L, R>
pub const fn in_array<O, const UL: usize, const UR: usize>(
self,
_other: O,
) -> TypeNe<[L; UL], [R; UR]>
pub const fn in_array<O, const UL: usize, const UR: usize>( self, _other: O, ) -> TypeNe<[L; UL], [R; UR]>
Combines TypeNe<L, R>
and a
O:
BaseTypeWitness
<L = Usize<UL>, R = Usize<UR>>
into TypeNe<[L; UL], [R; UR]>
§Example
use typewit::{const_marker::Usize, TypeCmp, TypeEq, TypeNe, type_ne};
const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
const NE_L: TypeNe<Usize<3>, Usize<5>> = Usize::<3>.equals(Usize::<5>).unwrap_ne();
const EQ_L: TypeEq<Usize<8>, Usize<8>> = TypeEq::NEW;
const TC_L: TypeCmp<Usize<13>, Usize<21>> = Usize::<13>.equals(Usize::<21>);
let _: TypeNe<[u8; 3], [i8; 5]> = NE.in_array(NE_L);
let _: TypeNe<[u8; 8], [i8; 8]> = NE.in_array(EQ_L);
let _: TypeNe<[u8; 13], [i8; 21]> = NE.in_array(TC_L);