typewit

Trait MakeTypeWitness

Source
pub trait MakeTypeWitness: TypeWitnessTypeArg {
    const MAKE: Self;
}
Expand description

Constructs this type witness.

A type witness is an enum whose variants only have TypeEq fields. Each variant requires the enum’s type parameter to be a specific type.

This trait can be automatically implemented for simple type witnesses by declaring the type witness with the simple_type_witness macro.

§Example

(this example requires Rust 1.61.0)

use typewit::{TypeWitnessTypeArg, MakeTypeWitness, TypeEq};
 
const fn default<'a, T, const L: usize>() -> T 
where
    Defaultable<'a, L, T>: MakeTypeWitness
{
    match MakeTypeWitness::MAKE {
        // `te` is a `TypeEq<T, i32>`, which allows coercing between `T` and `i32`.
        // `te.to_left(...)` goes from `i32` to `T`.
        Defaultable::I32(te) => te.to_left(3),

        // `te` is a `TypeEq<T, bool>`
        Defaultable::Bool(te) => te.to_left(true),

        // `te` is a `TypeEq<T, &'a str>`
        Defaultable::Str(te) => te.to_left("empty"),

        // `te` is a `TypeEq<T, [u32; L]>`
        Defaultable::Array(te) => te.to_left([5; L]),
    }
}
 
let number: i32 = default();
assert_eq!(number, 3);
 
let boolean: bool = default();
assert_eq!(boolean, true);
 
let string: &str = default();
assert_eq!(string, "empty");

let array: [u32; 3] = default();
assert_eq!(array, [5, 5, 5]);
 
 
// This enum is a type witness (documented in the root module)
#[non_exhaustive]
enum Defaultable<'a, const L: usize, T> {
    // This variant requires `T == i32`
    I32(TypeEq<T, i32>),

    // This variant requires `T == bool`
    Bool(TypeEq<T, bool>),

    // This variant requires `T == &'a str`
    Str(TypeEq<T, &'a str>),

    // This variant requires `T == [u32; L]`
    Array(TypeEq<T, [u32; L]>),
}
 
impl<T, const L: usize> TypeWitnessTypeArg for Defaultable<'_, L, T> {
    // this aids type inference for what type parameter is witnessed 
    type Arg = T;
}
 
// Specifying dummy values for the generics that the `I32` variant doesn't use,
// so that they don't have to be specified when this impl is used.
impl MakeTypeWitness for Defaultable<'_, 0, i32> {
    // The `TypeEq<T, i32>` field can be constructed because `T == i32` here.
    const MAKE: Self = Self::I32(TypeEq::NEW);
}
 
impl MakeTypeWitness for Defaultable<'_, 0, bool> {
    const MAKE: Self = Self::Bool(TypeEq::NEW);
}
 
impl<'a> MakeTypeWitness for Defaultable<'a, 0, &'a str> {
    const MAKE: Self = Self::Str(TypeEq::NEW);
}
 
impl<const L: usize> MakeTypeWitness for Defaultable<'_, L, [u32; L]> {
    const MAKE: Self = Self::Array(TypeEq::NEW);
}
 

The Defaultable type definition and its impls can also be written using the simple_type_witness macro:

typewit::simple_type_witness!{
    // Declares `enum Defaultable<'a, const L: usize, __Wit>`
    // The `__Wit` type parameter is implicit and always the last generic parameter.
    #[non_exhaustive]
    enum Defaultable<'a, const L: usize> {
        // `<'a, 0>` is necessary to have 
        // `impl MakeTypeWitness for Defaultable<'_, 0, i32>` instead of 
        // `impl<'a, const L: u32> MakeTypeWitness for Defaultable<'a, L, i32>`,
        // which allows the generic arguments to be inferred.
        I32<'a, 0> = i32,

        Bool<'a, 0> = bool,

        Str<'a, 0> = &'a str,

        Array = [u32; L],
    }
}

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.

Required Associated Constants§

Source

const MAKE: Self

A constant with the type witness

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<L: ?Sized, R: ?Sized> MakeTypeWitness for MetaBaseTypeWit<L, R, TypeCmp<L, R>>

Source§

const MAKE: Self = _

Source§

impl<L: ?Sized, R: ?Sized> MakeTypeWitness for MetaBaseTypeWit<L, R, TypeEq<L, R>>

Source§

const MAKE: Self = _

Source§

impl<L: ?Sized, R: ?Sized> MakeTypeWitness for MetaBaseTypeWit<L, R, TypeNe<L, R>>

Source§

const MAKE: Self = _

Source§

impl<T: ?Sized> MakeTypeWitness for TypeEq<T, T>

Source§

const MAKE: Self = Self::NEW

Source§

impl<const B: bool> MakeTypeWitness for BoolWitG<Bool<B>>

Source§

const MAKE: Self = _