typewit

Struct TypeNe

Source
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>

Source

pub const unsafe fn new_unchecked() -> TypeNe<L, R>

Constructs a TypeNe<L, R>.

§Safety

You must ensure that L != R.

Source§

impl TypeNe<(), ()>

Source

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>

Source

pub fn with_any() -> Option<Self>
where L: Sized + Any, R: Sized + Any,

👎Deprecated: fallout of 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());
 
Source

pub const fn to_cmp(self) -> TypeCmp<L, R>

Converts this TypeNe into a TypeCmp

§Example
use typewit::{TypeCmp, TypeNe, type_ne};
 
const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
const TC: TypeCmp<u8, i8> = NE.to_cmp();
 
assert!(matches!(TC, TypeCmp::Ne(_)));
Source

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();
 
Source

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);
}
Source

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>

Source

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);
 
Source

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)>
where A: BaseTypeWitness, B: BaseTypeWitness, A::L: Sized, A::R: Sized,

Combines this TypeNe<L, R> with two BaseTypeWitnesses 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());
 
Source

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 BaseTypeWitnesses 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>

§Why InjTypeFn

Both map and project require that the function is injective so that TypeNe’s arguments stay unequal.

pub const fn map<F>( self: TypeNe<L, R>, _func: F, ) -> TypeNe<CallInjFn<F, L>, CallInjFn<F, R>>
where F: InjTypeFn<L> + InjTypeFn<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>>
where F: InjTypeFn<L> + InjTypeFn<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>>
where F: RevTypeFn<L> + RevTypeFn<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>>
where F: RevTypeFn<L> + RevTypeFn<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>

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>

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>

pub const fn in_array<O, const UL: usize, const UR: usize>( self, _other: O, ) -> TypeNe<[L; UL], [R; UR]>
where O: BaseTypeWitness<L = Usize<UL>, R = Usize<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);
 

Trait Implementations§

Source§

impl<L: ?Sized, R: ?Sized> BaseTypeWitness for TypeNe<L, R>

Source§

type L = L

The L type parameter of TypeEq/TypeNe/TypeCmp types.
Source§

type R = R

The R type parameter of TypeEq/TypeNe/TypeCmp types.
Source§

impl<L: ?Sized, R: ?Sized> Clone for TypeNe<L, R>

Source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<L: ?Sized, R: ?Sized> Debug for TypeNe<L, R>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<L: ?Sized, R: ?Sized> Hash for TypeNe<L, R>

Source§

fn hash<H>(&self, _state: &mut H)
where H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<L: ?Sized, R: ?Sized> Ord for TypeNe<L, R>

Source§

fn cmp(&self, _: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<L: ?Sized, R: ?Sized> PartialEq for TypeNe<L, R>

Source§

fn eq(&self, _: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<L: ?Sized, R: ?Sized> PartialOrd for TypeNe<L, R>

Source§

fn partial_cmp(&self, _: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<L: ?Sized, R: ?Sized> Copy for TypeNe<L, R>

Source§

impl<L: ?Sized, R: ?Sized> Eq for TypeNe<L, R>

Auto Trait Implementations§

§

impl<L, R> Freeze for TypeNe<L, R>
where L: ?Sized, R: ?Sized,

§

impl<L, R> RefUnwindSafe for TypeNe<L, R>
where L: ?Sized, R: ?Sized,

§

impl<L, R> Send for TypeNe<L, R>
where L: ?Sized, R: ?Sized,

§

impl<L, R> Sync for TypeNe<L, R>
where L: ?Sized, R: ?Sized,

§

impl<L, R> Unpin for TypeNe<L, R>
where L: ?Sized, R: ?Sized,

§

impl<L, R> UnwindSafe for TypeNe<L, R>
where L: ?Sized, R: ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = const WITNESS: W = W::MAKE;

A constant of the type witness
Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = const TYPE_EQ: TypeEq<Self, Self::Type> = TypeEq::NEW;

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.