Remix.run Logo
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

    // inside crate C
    use A::impl std::hash::Hash for i32;
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

    HashMap<i32 + A::impl Hash, V>
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.

thunderseethe 3 days ago | parent [-]

I think rather than at odds with without.boats is saying, this is very much aligned with what they are suggesting. While not literally `use A::impl std::hash::Hash for i32` is for all intents and purposes naming the impl.

Similarly, `HashMap<i32 + A::impl Hash, V>` is what they are talking about when they refer to parameterizing code on the impl chosen.

atq2119 3 days ago | parent [-]

Essentially, yes. What I don't see is their claim that it's a "much greater annotation burden". Compared to what? Rust today just doesn't allow this at all, and if you use a wrapper type to simulate it, you definitely end up with more "annotations" (boilerplate).

couchand 3 days ago | parent [-]

FWIW It's not at all clear to me how this requirement would be implemented in practice: "This syntax would explicitly be limited to orphan implementations."

atq2119 3 days ago | parent [-]

Maybe I'm missing something, but the compiler can tell whether an implementation is an orphan. That's how you get an error message today if you try to write one. So I don't know what difficulty you have in mind.