We have two traits A
and B
for which
B
for all types that implement A
.A
for references to any type implementing A
.B
for references to any type implementing B
.Actually doing all three leads to a conflict, because now references to types that implement A
would have two implementations of B
for them. One due to the impl<T: A> A for &T
and one transitively due to the impl<T: A> B for T
(and then the impl<T: B> B for &T
.
I can't remove the impl<T: B> B for &T
, because there might be types that implement B
but not A
Here's an example code exhibiting the behaviour.
trait A {}
trait B {}
impl<'a, T: A> A for &'a T {}
impl<T: A> B for T {}
impl<'a, T: B> B for &'a T {}
which results in the following error:
error[E0119]: conflicting implementations of trait `B` for type `&_`:
|
| impl<T: A> B for T {}
| --------------------- first implementation here
| impl<'a, T: B> B for &'a T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
Is it possible to use the Rust typesystem in a way to ensure that when there is an impl B for &A
, we don't create one for &B
?
Implementing a trait on a type is similar to implementing regular methods. The difference is that after impl , we put the trait name we want to implement, then use the for keyword, and then specify the name of the type we want to implement the trait for.
An implementation is an item that associates items with an implementing type. Implementations are defined with the keyword impl and contain functions that belong to an instance of the type that is being implemented or to the type statically. There are two types of implementations: inherent implementations.
What are blanket implementations? Blanket implementations leverage Rust's ability to use generic parameters. They can be used to define shared behavior using traits. This is a great way to remove redundancy in code by reducing the need to repeat the code for different types with similar functionality.
A trait tells the Rust compiler about functionality a particular type has and can share with other types. Traits are an abstract definition of shared behavior amongst different types. So, we can say that traits are to Rust what interfaces are to Java or abstract classes are to C++.
There has been some discussion on the Rust internals forum on this topic, starting with a blog post by Nicholas Matsakis about how to handle the issue of overlapping trait implementations.
Today, (unstable) Rust has some impl specialisation, but that only works for strictly more specific impls of a more generic one.
So I think the answer is that there isn't a good way to do it today, but at some point in the future there's a good chance that Rust will evolve to allow expressing overlapping trait impls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With