The blanket impls are not really relevant, just used as an easy way to show the conflict. They just need to be impl over the same type, and have the same function name inside them. As the number of crates grows, naming overlaps are guaranteed to happen.
I agree, the fix in this case is easy. What's wrong with doing something similar for impl
? The compiler checks to make sure there is a unique definition for the trait. (This already would be an improvement from the current system.) If there is not, it asks you to clarify which impl
should be used.
For example:
Crate a
pub struct TypeA;
pub trait TraitA {
fn trait_func(&self);
}
Crate b
extern crate a;
use a::{TypeA, TraitA};
impl TraitA for TypeA {
fn trait_func(&self) {
println!("impl from b");
}
}
The compiler checks and finds that there is a unique definition, no problem. Then, the author of crate a implements the trait as well:
Crate a (new)
pub struct TypeA;
pub trait TraitA {
fn trait_func(&self);
}
impl TraitA for TypeA {
fn trait_func(&self) {
println!("impl from a");
}
}
When I go to compile crate b I receive an error, telling me that two implementations were found, and I need to either remove mine or specify which one should be used.
I guess my point is: this is just a namespace conflict. There are already namespace conflicts with regard to impl
as demonstrated above, and at the level of the method names these are allowed even though they have the potential to cause breaking changes, but at the level of the trait names they are not, and I'm not sure why.