I was inspired by this post to try to come up with a Rust equivalent. Indeed, I think it's possible to use traits to model arbitrary relational restrictions.
I'm still a newb at type system hacking, but I thought this was cool.
trait Person {}
trait Item {}
struct Warrior {}
impl Person for Warrior {}
struct Wizard {}
impl Person for Wizard {}
struct Sword {}
impl Item for Sword {}
struct Wand {}
impl Item for Wand {}
trait Wield<P: Person, I: Item> {
// this function is not meant to be used, but I believe is required to make the `P: Person, I: Item` trait restrictions stick
fn _f(p: P, i: I) {}
}
impl Wield<Warrior, Sword> for (Warrior, Sword) {
fn _f(p: Warrior, i: Sword) {}
}
impl Wield<Wizard, Wand> for (Wizard, Wand) {
fn _f(p: Wizard, i: Wand) {}
}
impl Wield<Wizard, Sword> for (Wizard, Sword) {
fn _f(p: Wizard, i: Sword) {}
}
struct Hero<P, I>
where
P: Person,
I: Item,
(P, I): Wield<P, I>,
{
p: P,
i: I,
}
fn main() {
let a = Hero {
p: Warrior {},
i: Sword {},
};
let b = Hero {
p: Wizard {},
i: Sword {},
};
let c = Hero {
p: Wizard {},
i: Wand {},
};
// this last one will err at compile time because it has not been enabled
let d = Hero {
p: Warrior {},
i: Wand {},
};
}