I’m also not an expert, but I’m thinking about this idea of disambiguating impl’s the way you would disambiguate methods.
So, if you have crate some_trait providing SomeTrait, and crate some_struct providing SomeStruct, and then crates foo and bar both implement SomeTrait for SomeStruct, then you have to disambiguate between, let’s call them foo::SomeTrait and bar::SomeTrait.
I guess the sticking point is when a crate that’s NOT foo or bar cares about SomeTrait. Such as the original crate, some_trait. In some_trait, you might have:
fn consumer <T: SomeTrait> (input: T) {…}
And then in my crate, baz, which imports both foo and bar, I do:
some_trait::consumer (SomeStruct::default());
In order to monomorphize consumer, it has to know not just T = SomeStruct, but T = SomeStruct with the SomeTrait impl from foo. Well, let’s assume I have a way to disambiguate that. I always prefer foo’s impl, so whenever I call a generic function that uses SomeTrait, it should use the impl from foo. I guess that includes even if I call a generic method from bar – after all, a generic method implemented in bar would have no reason to assume anything about the impl used for it.
I’ve been trying to think about counterintuitive cases that would arise from this, but it’s surprisingly difficult. Here’s the worst I’ve come up with so far:
//in some_trait
trait SomeTrait {
type Associated: Eq;
fn get_associated (&self)->Associated;
}
…
//In foo
impl SomeTrait for SomeStruct {type Associated = i64; …}
…
//in bar
impl SomeTrait for SomeStruct {type Associated = [i64; 2]; …}
fn complex_operation_returning_associated (input: &SomeStruct)->SomeStruct::Associated {…}
…
//In baz
prefer impl SomeTrait for SomeStruct from foo;
fn do_something (input: &SomeStruct)->bool {
//compile error, mismatched types
input.get_associated() == foo::complex_operation_returning_associated(input)
}