Function typewit::type_eq

source ·
pub const fn type_eq<T: ?Sized>() -> TypeEq<T, T>
Expand description

Constructs a TypeEq<T, T>

Example

use typewit::{MakeTypeWitness, TypeWitnessTypeArg, TypeEq, type_eq};
 
assert_eq!(ascii_to_upper(b'a'), b'A');
assert_eq!(ascii_to_upper(b'f'), b'F');
assert_eq!(ascii_to_upper(b'B'), b'B');
assert_eq!(ascii_to_upper(b'0'), b'0');
 
assert_eq!(ascii_to_upper('c'), 'C');
assert_eq!(ascii_to_upper('e'), 'E');
assert_eq!(ascii_to_upper('H'), 'H');
assert_eq!(ascii_to_upper('@'), '@');
 
const fn ascii_to_upper<T>(c: T) -> T 
where
    Wit<T>: MakeTypeWitness,
{
    match MakeTypeWitness::MAKE {
        Wit::U8(te) => {
            // `te` is a `TypeEq<T, u8>`, which allows casting between `T` and `u8`.
            // `te.to_right(...)` goes from `T` to `u8`
            // `te.to_left(...)` goes from `u8` to `T`
            te.to_left(te.to_right(c).to_ascii_uppercase())
        }
        Wit::Char(te) => {
            // `te` is a `TypeEq<T, char>`, which allows casting between `T` and `char`.
            // `te.to_right(...)` goes from `T` to `char`
            // `te.to_left(...)` goes from `char` to `T`
            te.to_left(te.to_right(c).to_ascii_uppercase())
        }
    }
}
 
// This is a type witness
enum Wit<T> {
    // this variant requires `T == u8`
    U8(TypeEq<T, u8>),
 
    // this variant requires `T == char`
    Char(TypeEq<T, char>),
}
impl<T> TypeWitnessTypeArg for Wit<T> {
    type Arg = T;
}
impl MakeTypeWitness for Wit<u8> {
    const MAKE: Self = Self::U8(type_eq());
}
impl MakeTypeWitness for Wit<char> {
    const MAKE: Self = Self::Char(type_eq());
}

The code above can be written more concisly using the polymatch and simple_type_witness macros:

const fn ascii_to_upper<T>(c: T) -> T 
where
    Wit<T>: MakeTypeWitness,
{
    // deduplicating identical match arms using the `polymatch` macro.
    typewit::polymatch!{MakeTypeWitness::MAKE;
        Wit::U8(te) | Wit::Char(te) => te.to_left(te.to_right(c).to_ascii_uppercase())
    }
}

// This macro declares a type witness
typewit::simple_type_witness! {
    // Declares `enum Wit<__Wit>`
    // The `__Wit` type parameter is implicit and always the last generic parameter.
    enum Wit {
        // this variant requires `__Wit == u8`
        U8 = u8,
        // this variant requires `__Wit == char`
        Char = char,
    }
}

note that simple_type_witness can’t replace enums whose witnessed type parameter is not the last, or have variants with anything but one TypeEq field each.