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§
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.