▲ | withoutboats3 3 days ago | ||||||||||||||||||||||||||||||||||
Implementations are not imported at all because they are not named. Like I wrote, named implementations (ala ML modules) is a valid alternative, but one with a much greater annotation burden. You could imagine having named impls that are allowed to be incoherent as an additional feature on top of coherent unnamed impls, but to use them you would need to make any code that depends on their behavior parameterized by the impl as well as the types. In fact, you can pretty trivially emulate that behavior in Rust today by adding a dummy type parameter to your type and traits. Again, it's all a set of trade offs. | |||||||||||||||||||||||||||||||||||
▲ | atq2119 3 days ago | parent [-] | ||||||||||||||||||||||||||||||||||
Right, but what I'm describing is a tradeoff point that's between the extremes, where implementations are unnamed but can still be explicitly imported. Making my example more explicit, you'd need syntax along the lines of
This syntax would explicitly be limited to orphan implementations.I suppose to further clarify, there's still some coherence requirement there in that crate C can't import the conflicting implementations from both A and B. Which could then perhaps be worked around by adding syntax to spell types along the lines of
Which you could argue is a form of naming implementations, I suppose? I'm not familiar with ML. You could maybe also think of it as a more ergonomic way of doing (more or less) those wrapper types.In any case, the annotation burden only exists where it's actually needed to enable orphan implementations. And either way, multiple different impls can safely coexist within the overall set of code that's linked together, with everything being statically checked at compile time. | |||||||||||||||||||||||||||||||||||
|