Disclaimer: This seems to have been suggested back in 2014, but back then people were suggesting using negative trait bounds as an alternative. As those aren't really something we want to make widely available, I think we need another solution.
The problem: It feels to me that traits aren't really done yet. They promote a "design by contract" approach, but while it's possible to say "if I can do Foo AND Bar, then I can do Baz," it's not really possible right now to say "if I can do Foo OR Bar, then I can do Baz." This severely limits the scope of what you can do with traits.
The problem with the natural approach (implementing a trait multiple times with different trait bounds) is that currently the compiler doesn't know what to do in the case where both sets of bounds are met. For instance:
// What do you compile in the case where `T: Foo + Bar`?
impl<T: Foo> SomeTrait for T {}
impl<T: Bar> SomeTrait for T {}
Proposed solution: Specialisation seems really useful, but only really gets us part of the way there. The proposed solution is to instead manually decide which impl
block gets priority, like this:
trait SomeTrait {
fn do_something(self);
}
trait Foo {
fn foo(self);
}
trait Bar {
fn bar(self);
}
#[priority(0)]
impl<T: Foo> SomeTrait for T {
fn do_something(self) {
self.foo()
}
}
#[priority(1)]
impl<T: Bar> SomeTrait for T {
fn do_something(self) {
self.bar()
}
}
If T:Foo
, then do_something()
will call foo()
. If T:Bar
, then do_something()
will call bar()
, but most importantly, if T:Foo+Bar
, then do_something()
will call foo()
, as we've manually specified which version to compile when both impl
blocks are valid.
What's more, this system could be extended to other areas where trait bounds might conflict with each-other. For instance, you might want to have different implementations of the same function to relax the bounds on its parameters. A #[priority]
attribute would allow you to do that.
Overall, I think that having something like this in the language would allow for much greater power and control when using traits and generics, and could be very positive for the ecosystem as a whole. Given that negative trait bounds are a no-go, how would people feel about having this feature in the language?