konst_kernel::type_eq

Struct TypeEq

Source
pub struct TypeEq<L, R>(/* private fields */)
where
    L: ?Sized,
    R: ?Sized;
Expand description

Value-level proof that L is the same type as R

This type can be used to prove that L and R are the same type, because it can only be safely constructed with TypeEq::<L, L>::NEW(or new), where both type arguments are the same type.

This type is not too useful by itself, it becomes useful when put inside of an enum.

TypeEq<L, R> uses the L type parameter as the more generic type by convention (e.g: TypeEq<T, char>). This only matters if you’re using the type witness traits (HasTypeWitness, MakeTypeWitness, TypeWitnessTypeArg) with TypeEq.

§Soundness

TypeEq<L, R> requires both type arguments to be the same type so that projecting the type arguments results in the same type for both arguments.

Unsafely creating a TypeEq<L, R> where L != R allows transmuting between any two types (that is bad).

§Examples

§Polymorphic branching

This example demonstrates how type witnesses can be used to choose between expressions of different types with a constant.

use typewit::TypeEq;
 
const fn main() {
    assert!(matches!(choose!(0; b"a string", 2, panic!()), b"a string"));
 
    const UNO: u64 = 1;
    assert!(matches!(choose!(UNO; loop{}, [3, 5], true), [3, 5]));
 
    assert!(matches!(choose!(2 + 3; (), unreachable!(), ['5', '3']), ['5', '3']));
}
 
/// Evaluates the argument at position `$chosen % 3`, other arguments aren't evaluated.
/// 
/// The arguments can all be different types.
/// 
/// `$chosen` must be a `u64` constant.
#[macro_export]
macro_rules! choose {
    ($chosen:expr; $arg_0: expr, $arg_1: expr, $arg_2: expr) => {
        match Choice::<{$chosen % 3}>::VAL {
            // `te` (a `TypeEq<T, X>`) allows us to safely go between 
            // the type that the match returns (its `T` type argument)
            // and the type of `$arg_0` (its `X` type argument).
            Branch3::A(te) => {
                // `to_left` goes from `X` to `T`
                te.to_left($arg_0)
            }
            // same as the `A` branch, with a different type for the argument
            Branch3::B(te) => te.to_left($arg_1),
            // same as the `A` branch, with a different type for the argument
            Branch3::C(te) => te.to_left($arg_2),
        }
    }
}
 
// This is a type witness
pub enum Branch3<T, X, Y, Z> {
    // This variant requires `T == X`
    A(TypeEq<T, X>),
 
    // This variant requires `T == Y`
    B(TypeEq<T, Y>),
 
    // This variant requires `T == Z`
    C(TypeEq<T, Z>),
}
 
// Used to get different values of `Branch3` depending on `N`
pub trait Choice<const N: u64> {
    const VAL: Self;
}
 
impl<X, Y, Z> Choice<0> for Branch3<X, X, Y, Z> {
    // Because the first two type arguments of `Branch3` are `X`
    // (as required by the `TypeEq<T, X>` field in Branch3's type definition),
    // we can use `TypeEq::NEW` here.
    const VAL: Self = Self::A(TypeEq::NEW);
}
 
impl<X, Y, Z> Choice<1> for Branch3<Y, X, Y, Z> {
    const VAL: Self = Self::B(TypeEq::NEW);
}
 
impl<X, Y, Z> Choice<2> for Branch3<Z, X, Y, Z> {
    const VAL: Self = Self::C(TypeEq::NEW);
}
 

Implementations§

Source§

impl<T> TypeEq<T, T>
where T: ?Sized,

Source

pub const NEW: TypeEq<T, T> = _

Constructs a TypeEq<T, T>.

§Example
use typewit::TypeEq;
 
assert_eq!(mutate(5, Wit::U32(TypeEq::NEW)), 25);
 
assert_eq!(mutate(5, Wit::Other(TypeEq::NEW)), 5);
assert_eq!(mutate("hello", Wit::Other(TypeEq::NEW)), "hello");
 
const fn mutate<W>(val: W, wit: Wit<W>) -> W {
    match wit {
        Wit::U32(te) => te.to_left(te.to_right(val) + 20),
        Wit::Other(_) => val,
    }
}
 
// This can't be written using the `simple_type_witness` macro because the 
// type in the `Other` variant overlaps with the other ones.
enum Wit<W> {
    U32(TypeEq<W, u32>),
    Other(TypeEq<W, W>),
}
Source§

impl TypeEq<(), ()>

Source

pub const fn new<T>() -> TypeEq<T, T>
where T: ?Sized,

Constructs a TypeEq<T, T>.

Source§

impl<L, R> TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source

pub fn with_any() -> Option<TypeEq<L, R>>
where L: Any, R: Any,

Constructs TypeEq<L, R> if L == R, otherwise returns None.

§Example
use typewit::TypeEq;
 
use std::any::Any;
 
assert_eq!(sum_u32s(&[3u32, 5, 8]), Some(16));
assert_eq!(sum_u32s(&[3i32, 5, 8]), None);
 
 
fn sum_u32s<T: Clone + Any>(foo: &[T]) -> Option<u32> {
    typecast_slice::<T, u32>(foo)
        .map(|foo: &[u32]| foo.iter().copied().sum())
}
 
fn typecast_slice<T: Any, U: Any>(foo: &[T]) -> Option<&[U]> {
    struct SliceFn;
    impl<T> typewit::TypeFn<T> for SliceFn {
        type Output = [T];
    }
 
    TypeEq::<T, U>::with_any().map(|te: TypeEq<T, U>|{
        te.map(SliceFn) // TypeEq<[T], [U]>
          .in_ref()   // TypeEq<&[T]>, &[U]>
          .to_right(foo) // identity cast from `&[T]` to `&[U]`
    })
}
Source

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

Constructs a TypeEq<L, R>.

§Safety

You must ensure that L is the same type as R.

§Examples
§Unsound usage

This example demonstrates why L == R is a strict requirement.

use typewit::{TypeEq, TypeFn};

// SAFETY: WRONG! UNSOUND!
let te: TypeEq<u8, i8> = unsafe{ TypeEq::new_unchecked() };
 
// Because `TypeEq<u8, i8>` is incorrect,
// we get this absurd `TypeEq` from the `project` method.
let absurd: TypeEq<(), Vec<usize>> = te.project::<Func>();
 
// This casts from `()` to `Vec<usize>` (which is UB).
// Last time I tried uncommenting this, it killed the test runner.
// absurd.to_right(()); 
 
struct Func;
impl TypeFn<u8> for Func { type Output = (); }
impl TypeFn<i8> for Func { type Output = Vec<usize>; }

Source§

impl<L, R> TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source

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

Converts this TypeEq into a TypeCmp

§Example
use typewit::{TypeCmp, TypeEq};
 
const TC: TypeCmp<bool, bool> = TypeEq::NEW.to_cmp();
 
assert!(matches!(TC, TypeCmp::Eq(_)));
Source

pub const fn flip(self) -> TypeEq<R, L>

Swaps the type parameters of this TypeEq

§Example
use typewit::TypeEq;
 
assert_eq!(flip_bytes([3, 5], TypeEq::NEW), [5, 3]);
 
const fn flip_bytes<T>(val: T, te: TypeEq<T, [u8; 2]>) -> T {
    bar(val, te.flip())
}
const fn bar<T>(val: T, te: TypeEq<[u8; 2], T>) -> T {
    let [l, r] = te.to_left(val);
    te.to_right([r, l])
}
Source

pub const fn join<O>(self, _other: TypeEq<R, O>) -> TypeEq<L, O>
where O: ?Sized,

Joins this TypeEq<L, R> with a TypeEq<R, O>, producing a TypeEq<L, O>.

The returned TypeEq can then be used to coerce between L and O.

§Example
use typewit::TypeEq;
 
assert_eq!(foo(TypeEq::NEW, TypeEq::NEW, Some(3)), Some(3));
assert_eq!(foo(TypeEq::NEW, TypeEq::NEW, None), None);
 
 
fn foo<L, X>(
    this: TypeEq<L, Option<X>>,
    that: TypeEq<Option<X>, Option<u32>>,
    value: Option<u32>,
) -> L {
    let te: TypeEq<L, Option<u32>> = this.join(that);
    te.to_left(value)
}
 
Source§

impl<L0, R0> TypeEq<L0, R0>

Source

pub const fn zip<L1, R1>( self, other: TypeEq<L1, R1>, ) -> TypeEq<(L0, L1), (R0, R1)>
where L1: ?Sized, R1: ?Sized,

Combines this TypeEq<L0, R0> with a TypeEq<L1, R1>, producing a TypeEq<(L0, L1), (R0, R1)>.

§Alternative

For an alternative which allows zipping TypeEq with any BaseTypeWitness, you can use methods::zip2 (requires the "rust_1_65" feature)

§Example

This example demonstrates how one can combine two TypeEqs to use with a multi-parameter type.

use typewit::{const_marker::Usize, TypeEq, TypeFn};
 
assert_eq!(make_foo(TypeEq::NEW, TypeEq::NEW), Foo("hello", [3, 5, 8]));
 
const fn make_foo<T, const N: usize>(
    te_ty: TypeEq<T, &'static str>,
    te_len: TypeEq<Usize<N>, Usize<3>>,
) -> Foo<T, N> {
    // the type annotations are just for the reader, they can be inferred.
    let te_pair: TypeEq<(T, Usize<N>), (&str, Usize<3>)> = te_ty.zip(te_len);
 
    let te: TypeEq<Foo<T, N>, Foo<&str, 3>> = te_pair.project::<GFoo>();
 
    // `te.to_left(...)` here goes from `Foo<&str, 3>` to `Foo<T, N>`
    te.to_left(Foo("hello", [3, 5, 8]))
}
 
#[derive(Debug, PartialEq)]
struct Foo<T, const N: usize>(T, [u8; N]);
 
typewit::type_fn!{
    // Type-level function from `(T, Usize<N>)` to `Foo<T, N>`
    struct GFoo;

    impl<T, const N: usize> (T, Usize<N>) => Foo<T, N>
}
Source

pub const fn zip3<L1, R1, L2, R2>( self, other1: TypeEq<L1, R1>, other2: TypeEq<L2, R2>, ) -> TypeEq<(L0, L1, L2), (R0, R1, R2)>
where L2: ?Sized, R2: ?Sized,

Combines three TypeEq<L*, R*> to produce a TypeEq<(L0, L1, L2), (R0, R1, R2)>.

§Alternative

For an alternative which allows zipping TypeEq with two of any BaseTypeWitness, you can use methods::zip3 (requires the "rust_1_65" feature)

§Example
use typewit::{TypeEq, type_eq};
 
use std::cmp::Ordering::{self, Less};
 
assert_eq!(make_tuple(type_eq(), type_eq(), type_eq()), (3, "foo", Less));
 
fn make_tuple<A, B, C>(
    te0: TypeEq<A, u8>,
    te1: TypeEq<B, &str>,
    te2: TypeEq<C, Ordering>,
) -> (A, B, C) {
    te0.zip3(te1, te2) // returns `TypeEq<(A, B, C), (u8, &str, Ordering)>`
        .to_left((3, "foo", Less))
}
 
Source

pub const fn zip4<L1, R1, L2, R2, L3, R3>( self, other1: TypeEq<L1, R1>, other2: TypeEq<L2, R2>, other3: TypeEq<L3, R3>, ) -> TypeEq<(L0, L1, L2, L3), (R0, R1, R2, R3)>
where L3: ?Sized, R3: ?Sized,

Combines four TypeEq<L*, R*> to produce a TypeEq<(L0, L1, L2, L3), (R0, R1, R2, L3)>.

§Alternative

For an alternative which allows zipping TypeEq with three of any BaseTypeWitness, you can use methods::zip4 (requires the "rust_1_65" feature)

§Example
use typewit::{TypeEq, type_eq};
 
use std::cmp::Ordering::{self, Less};
 
assert_eq!(
    make_tuple(type_eq(), type_eq(), type_eq(), type_eq()), 
    (3, "foo", Less, true),
);
 
fn make_tuple<A, B, C, D>(
    te0: TypeEq<A, u8>,
    te1: TypeEq<B, &str>,
    te2: TypeEq<C, Ordering>,
    te3: TypeEq<D, bool>,
) -> (A, B, C, D) {
    let te: TypeEq<(A, B, C, D), (u8, &str, Ordering, bool)> = te0.zip4(te1, te2, te3);
    te.to_left((3, "foo", Less, true))
}
 
Source§

impl<L, R> TypeEq<L, R>

Source

pub const fn reachability_hint<T>(self, val: T) -> T

Hints to the compiler that a TypeEq<L, R> can only be constructed if L == R.

This function takes and returns val unmodified. This allows returning some value from an expression while hinting that L == R.

Source

pub const fn to_right(self, from: L) -> R

A no-op cast from L to R.

This cast is a no-op because having a TypeEq<L, R> value proves that L and R are the same type.

§Example
use typewit::{TypeEq, type_eq};
 
use std::cmp::Ordering::{self, *};
 
assert_eq!(mutated(Less, Wit::Ord(type_eq())), Greater);
assert_eq!(mutated(Equal, Wit::Ord(type_eq())), Equal);
assert_eq!(mutated(Greater, Wit::Ord(type_eq())), Less);
 
assert_eq!(mutated(false, Wit::Bool(type_eq())), true);
assert_eq!(mutated(true, Wit::Bool(type_eq())), false);
 
const fn mutated<R>(arg: R, w: Wit<R>) -> R {
    match w {
        Wit::Ord(te) => te.to_left(te.to_right(arg).reverse()),
        Wit::Bool(te) => te.to_left(!te.to_right(arg)),
    }
}
 
enum Wit<R> {
    Ord(TypeEq<R, Ordering>),
    Bool(TypeEq<R, bool>),
}
Source

pub const fn to_left(self, from: R) -> L

A no-op cast from R to L.

This cast is a no-op because having a TypeEq<L, R> value proves that L and R are the same type.

§Example
use typewit::{TypeEq, type_eq};
 
assert_eq!(stuff(Wit::OptSlice(type_eq())), Some(&[3, 5, 8][..]));
assert_eq!(stuff(Wit::Bool(type_eq())), true);
 
const fn stuff<R>(te: Wit<R>) -> R {
    match te {
        Wit::OptSlice(te) => te.to_left(Some(&[3, 5, 8])),
        Wit::Bool(te) => te.to_left(true),
    }
}
 
enum Wit<R> {
    OptSlice(TypeEq<R, Option<&'static [u16]>>),
    Bool(TypeEq<R, bool>),
}
Source§

impl<L, R> TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source

pub const fn map<F>( self, func: F, ) -> TypeEq<<F as TypeFn<L>>::Output, <F as TypeFn<R>>::Output>
where F: TypeFn<L> + TypeFn<R>,

Maps the type arguments of this TypeEq by using the F type-level function.

Use this function over project if you want the type of the passed in function to be inferred.

§Example
use typewit::{TypeEq, TypeFn};
 
assert_eq!(foo(TypeEq::NEW), (false, 5));
 
const fn foo<'a, T>(te: TypeEq<u32, T>) -> (bool, T) {
    // `GPair<bool>` maps `u32` to `(bool, u32)`
    //           and maps `T`   to `(bool, T)`
    let map_te: TypeEq<(bool, u32), (bool, T)> = te.map(GPair::<bool>::NEW); 
 
    // same as the above, but inferring `GPair`'s generic arguments.
    let _: TypeEq<(bool, u32), (bool, T)> = te.map(GPair::NEW); 
 
    map_te.to_right((false, 5u32))
}
 
// Declares `struct GPair<A>`, a type-level function from `B` to `(A, B)` 
typewit::type_fn! {
     struct GPair<A>;
 
     impl<B> B => (A, B)
} 
Source

pub const fn project<F>( self, ) -> TypeEq<<F as TypeFn<L>>::Output, <F as TypeFn<R>>::Output>
where F: TypeFn<L> + TypeFn<R>,

Maps the type arguments of this TypeEq by using the F type-level function.

Use this function over map if you want to specify the type of the passed in function explicitly.

§Example
use typewit::{TypeEq, TypeFn};
 
assert_eq!(foo(TypeEq::NEW), vec![3u32, 5, 8]);
 
fn foo<T>(te: TypeEq<u32, T>) -> Vec<T> {
    let vec_te: TypeEq<Vec<u32>, Vec<T>> = te.project::<GVec>();
    vec_te.to_right(vec![3, 5, 8])
}
 
// Declares `GVec`, a type-level function from `T` to `Vec<T>`
typewit::type_fn!{
    struct GVec;
 
    impl<T> T => Vec<T>
}
 
Source§

impl<L, R> TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source

pub const fn unmap<F>( self, func: F, ) -> TypeEq<<F as RevTypeFn<L>>::Arg, <F as RevTypeFn<R>>::Arg>
where F: RevTypeFn<L> + RevTypeFn<R>,

Maps the type arguments of this TypeEq 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::{TypeEq, UncallFn};
 
assert_eq!(first_int(&[3, 5, 8, 13], TypeEq::NEW), 3);
 
const fn first_int<T, const N: usize>(
    array: &[T; N],
    te_slice: TypeEq<[T], [u8]>,
) -> u8 {
    let te: TypeEq<T, u8> = te_slice.unmap(SliceFn);

    let te_ref: TypeEq<&T, &u8> = te.in_ref();

    *te_ref.to_right(&array[0])
}

typewit::inj_type_fn! {
    struct SliceFn;
 
    impl<T> T => [T]
}
Source

pub const fn unproject<F>( self, ) -> TypeEq<<F as RevTypeFn<L>>::Arg, <F as RevTypeFn<R>>::Arg>
where F: RevTypeFn<L> + RevTypeFn<R>,

Maps the type arguments of this TypeEq 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::TypeEq;
use std::ops::{Range, RangeInclusive as RangeInc};
 
assert_eq!(usize_bounds(3..=5, TypeEq::NEW), (3, 5));
 
const fn usize_bounds<T>(
    range: RangeInc<T>,
    te_range: TypeEq<Range<T>, Range<usize>>,
) -> (usize, usize) {
    let te: TypeEq<T, usize> = te_range.unproject::<RangeFn>();
     
    let te_range_inc: TypeEq<RangeInc<T>, RangeInc<usize>> = te.project::<RangeIncFn>();
     
    let range: RangeInc<usize> = te_range_inc.to_right(range);
     
    (*range.start(), *range.end())
}
 
typewit::inj_type_fn! {
    struct RangeFn;
 
    impl<T> T => Range<T>
}
typewit::inj_type_fn! {
    struct RangeIncFn;
 
    impl<T> T => RangeInc<T>
}
Source§

impl<L, R> TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source

pub const fn in_ref<'a>(self) -> TypeEq<&'a L, &'a R>

Converts a TypeEq<L, R> to TypeEq<&L, &R>

§Example
use typewit::{MakeTypeWitness, TypeEq};
 
assert_eq!(get::<u8>(), &3);
assert_eq!(get::<str>(), "hello");
 
 
const fn get<R: ?Sized>() -> &'static R 
where
    Returned<R>: MakeTypeWitness
{
    match MakeTypeWitness::MAKE {
        // `te` is a `TypeEq<R, u8>`
        Returned::U8(te) => te.in_ref().to_left(&3),

        // `te` is a `TypeEq<R, str>`
        Returned::Str(te) => te.in_ref().to_left("hello"),
    }
}
 
typewit::simple_type_witness! {
    // declares the `enum Returned<R> {` type witness
    enum Returned {
        // this variant requires `R == u8`
        U8 = u8,
        // this variant requires `R == str`
        Str = str,
    }
}
Source

pub fn in_mut<'a>(self) -> TypeEq<&'a mut L, &'a mut R>

Converts a TypeEq<L, R> to TypeEq<&mut L, &mut R>

§Constness

This requires the "rust_1_83" feature to be a const fn.

§Example

Because this example calls in_mut inside a const fn, it requires the "rust_1_83" crate feature.

 
 use typewit::{TypeEq, type_eq};
 
 let foo = &mut Foo { bar: 10, baz: ['W', 'H', 'O'] };
 
 *get_mut(foo, Field::Bar(type_eq())) *= 2;
 assert_eq!(foo.bar, 20);
 
 assert_eq!(*get_mut(foo, Field::Baz(type_eq())), ['W', 'H', 'O']);
 
 
 const fn get_mut<R>(foo: &mut Foo, te: Field<R>) -> &mut R {
     match te {
         Field::Bar(te) => te.in_mut().to_left(&mut foo.bar),
         Field::Baz(te) => te.in_mut().to_left(&mut foo.baz),
     }
 }
 
 struct Foo {
     bar: u8,
     baz: [char; 3],
 }
 
 enum Field<R: ?Sized> {
     Bar(TypeEq<R, u8>),
     Baz(TypeEq<R, [char; 3]>),
 }
Source§

impl<L, R> TypeEq<L, R>

Source

pub const fn in_array<const UL: usize, const UR: usize>( self, other: TypeEq<Usize<UL>, Usize<UR>>, ) -> TypeEq<[L; UL], [R; UR]>

Combines TypeEq<L, R> and TypeEq<Usize<UL>, Usize<UR>> into TypeEq<[L; UL], [R; UR]>

§Alternative

For an alternative which allows passing any BaseTypeWitness for the length, you can use methods::in_array (requires the "rust_1_65" feature)

§Example
motivation

The safe way to map an array in const fns(on stable Rust in 2023) is to create an array of the returned type with some dummy value, and then fill it in with the desired values.

Because the function in this example takes a [T; LEN] where the T is generic, it copies the first element of the input array to initialize the returned array, so we must handle empty arrays, but trying to return an empty array the naive way

    if LEN == 0 {
        return [];
    }

does not work

error[E0308]: mismatched types
 --> src/type_eq.rs:827:16
  |
4 | const fn map_wrapping<T: Copy, const LEN: usize>(arr: [T; LEN]) -> [Wrapping<T>; LEN] {
  |                                                                    ------------------ expected `[Wrapping<T>; LEN]` because of return type
5 |     if LEN == 0 {
6 |         return [];
  |                ^^ expected `LEN`, found `0`
  |
  = note: expected array `[Wrapping<T>; LEN]`
             found array `[_; 0]`
 

This example demonstrates how in_array allows one to return an empty array: (this example requires Rust 1.61.0, because it uses trait bounds in const fns)

use typewit::{const_marker::Usize, TypeCmp, TypeEq};
 
use std::num::Wrapping;
 
assert_eq!(map_wrapping([""; 0]), []);
assert_eq!(map_wrapping([3, 5, 8]), [Wrapping(3), Wrapping(5), Wrapping(8)]);
 
const fn map_wrapping<T: Copy, const LEN: usize>(arr: [T; LEN]) -> [Wrapping<T>; LEN] {
    // `teq` is a `TypeEq<Usize<LEN>, Usize<0>>`
    if let TypeCmp::Eq(teq) = Usize::<LEN>.equals(Usize::<0>) {
        return TypeEq::new::<Wrapping<T>>()
            .in_array(teq) // `TypeEq<[Wrapping<T>; LEN], [Wrapping<T>; 0]>`
            .to_left([]);
    }
     
    let mut ret = [Wrapping(arr[0]); LEN];
    let mut i = 1;
     
    while i < LEN {
        ret[i] = Wrapping(arr[i]);
        i += 1;
    }
     
    ret
}

Trait Implementations§

Source§

impl<L, R> BaseTypeWitness for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

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, R> Clone for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

fn clone(&self) -> TypeEq<L, R>

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, R> Debug for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

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

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

impl<T> Default for TypeEq<T, T>
where T: ?Sized,

Source§

fn default() -> TypeEq<T, T>

Returns the “default value” for a type. Read more
Source§

impl<L, R> Hash for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

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<T> MakeTypeWitness for TypeEq<T, T>
where T: ?Sized,

Source§

const MAKE: TypeEq<T, T> = Self::NEW

A constant with the type witness
Source§

impl<L, R> Ord for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

fn cmp(&self, _: &TypeEq<L, R>) -> 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, R> PartialEq for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

fn eq(&self, _: &TypeEq<L, R>) -> 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, R> PartialOrd for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

fn partial_cmp(&self, _: &TypeEq<L, R>) -> 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, R> TypeWitnessTypeArg for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

type Arg = L

The type parameter used for type witnesses. Read more
Source§

impl<L, R> Copy for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Source§

impl<L, R> Eq for TypeEq<L, R>
where L: ?Sized, R: ?Sized,

Auto Trait Implementations§

§

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

§

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

§

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

§

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

§

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

§

impl<L, R> UnwindSafe for TypeEq<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 = 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> = 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.