Struct typewit::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,

Available on crate feature rust_1_61 only.

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,

Available on crate feature rust_1_61 only.

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,

Available on crate feature rust_1_61 only.

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 const 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 either of the "mut_refs" or "const_mut_refs" crate features to be enabled 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
}

pub const fn in_box(self) -> TypeNe<Box<L>, Box<R>>

Available on crate feature alloc only.

Converts a TypeNe<L, R> to TypeNe<Box<L>, Box<R>>

Example
use typewit::{TypeNe, inj_type_fn, type_ne};
 
use std::num::{NonZeroI8, NonZeroU8};
 
const NE: TypeNe<NonZeroI8, NonZeroU8> = type_ne!(NonZeroI8, NonZeroU8);
 
let foo: NonZeroI8 = NonZeroI8::new(-1).unwrap();
let bar: NonZeroU8 = NonZeroU8::new(1).unwrap();
 
baz(Box::new(foo), Box::new(bar), NE.in_box());
 
fn baz<T, U>(foo: Box<T>, bar: Box<U>, _ne: TypeNe<Box<T>, Box<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>>,

Available on crate feature rust_1_61 only.

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>

§

type L = L

Available on crate feature rust_1_61 only.
The L type parameter of TypeEq/TypeNe/TypeCmp types.
§

type R = R

Available on crate feature rust_1_61 only.
The R type parameter of TypeEq/TypeNe/TypeCmp types.
§

type TypeCtor = TcTypeNe

Available on crate features rust_1_61 and rust_1_65 only.
The type constructor corresponding to this type.
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 + PartialOrd,

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

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

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

This method 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

This method 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

This method 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

This method 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

This method 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: ?Sized, R: ?Sized> RefUnwindSafe for TypeNe<L, R>

§

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

§

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

§

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

§

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

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

§

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§

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§

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> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

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

§

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

§

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.