pub struct True;
pub struct False;
pub trait Bool {
type If<Then, Else>;
}
impl Bool for True {
type If<Then, Else> = Then;
}
impl Bool for False {
type If<Then, Else> = Else;
}
pub trait CapSet {
type HasClone: Bool;
type HasCopy: Bool;
}
pub struct IsClone;
pub struct IsCopy;
pub trait Select<Query, Then, Else> {
type Out;
}
impl<C, Then, Else> Select<IsClone, Then, Else> for C
where
C: CapSet,
C::HasClone: Bool,
{
type Out = <C::HasClone as Bool>::If<Then, Else>;
}
pub trait SelectClone<Then, Else> {
type Out;
}
impl<C, Then, Else> SelectClone<Then, Else> for C
where
C: CapSet,
{
type Out = <C::HasClone as Bool>::If<Then, Else>;
}
pub trait SelectCopy<Then, Else> {
type Out;
}
impl<C, Then, Else> SelectCopy<Then, Else> for C
where
C: CapSet,
{
type Out = <C::HasCopy as Bool>::If<Then, Else>;
}
pub trait DescribeImpl<T: ?Sized> {
fn describe(value: &T) -> &'static str;
}
pub struct CloneDescribe;
impl<T: ?Sized> DescribeImpl<T> for CloneDescribe {
fn describe(_: &T) -> &'static str {
"Has Clone (Type-Level)"
}
}
pub struct DefaultDescribe;
impl<T: ?Sized> DescribeImpl<T> for DefaultDescribe {
fn describe(_: &T) -> &'static str {
"General (Type-Level)"
}
}
pub trait Describe {
fn describe(&self) -> &'static str;
}
impl<T> Describe for T
where
T: CapSet,
T: SelectClone<CloneDescribe, DefaultDescribe>,
<T as SelectClone<CloneDescribe, DefaultDescribe>>::Out: DescribeImpl<T>,
{
fn describe(&self) -> &'static str {
<T as SelectClone<CloneDescribe, DefaultDescribe>>::Out::describe(self)
}
}
#[derive(Clone)]
struct HasClone;
impl CapSet for HasClone {
type HasClone = True;
type HasCopy = False;
}
struct NoClone;
impl CapSet for NoClone {
type HasClone = False;
type HasCopy = False;
}
#[derive(Clone, Copy)]
struct HasBoth;
impl CapSet for HasBoth {
type HasClone = True;
type HasCopy = True;
}
fn main() {
println!("==================================================================");
println!(" TYPE-LEVEL DISPATCH PROTOTYPE V2");
println!(" No `if` - Pure Type Selection (Stable Rust!)");
println!("==================================================================\n");
let has_clone = HasClone;
let no_clone = NoClone;
let has_both = HasBoth;
println!("Type-Level Dispatch Results:");
println!(" HasClone: {}", has_clone.describe());
println!(" NoClone: {}", no_clone.describe());
println!(" HasBoth: {}", has_both.describe());
assert_eq!(has_clone.describe(), "Has Clone (Type-Level)");
assert_eq!(no_clone.describe(), "General (Type-Level)");
assert_eq!(has_both.describe(), "Has Clone (Type-Level)");
println!();
println!("==================================================================");
println!(" TYPE-LEVEL DISPATCH WORKS ON STABLE!");
println!(" No if branches, pure type selection");
println!("==================================================================");
}