Just making sure I understand coherence correctly. This restriction conceptually doesn't make sense, right?
struct LocalType;
impl<I> LocalTrait for I where I: IntoIterator<Item = LocalType> {}
trait LocalTrait {}
impl LocalTrait for &[u8] {}
yields
error[E0119]: conflicting implementations of trait `LocalTrait` for type `&[u8]`
--> src/lib.rs:7:1
|
3 | impl<I> LocalTrait for I where I: IntoIterator<Item = LocalType> {}
| ------------------------ first implementation here
...
7 | impl LocalTrait for &[u8] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&[u8]`
|
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `&[u8]` in future versions
On first glance, this does indeed look like rustc is simply not smart enough here. This isnāt helped by the fact that thereās a general T: IntoIterator impl for T: Iterator. Maybe the compiler would be less confused without such a blanket impl around. Nevermind, thatās easily ruled out, too.
This situation may be related how impls like this wonāt compile either due to āoverlapā
struct LocalType1;
struct LocalType2;
trait LocalTrait {}
impl<I> LocalTrait for I where I: Iterator<Item = LocalType1> {}
impl<I> LocalTrait for I where I: Iterator<Item = LocalType2> {}
Coherence does not take associated types into account in any situation to my knowledge. I have no doubt it would be accepted if someone cared enough to implement it.
I have even worse case of unnecessary strictness of the current constraints:
pub trait LocalTrait { .. }
impl<T: LocalTrait> ThridPartyTrait for T { .. }
Another crate will not be able to implement both LocalTrait and ThridPartyTrait for its local type, because the blanket impl would cause a compilation error. There are ways for working around it (blanket impl for dyn LocalTrait or introduction of wrappers), but they are quite unpleasant.
This is something that sealed traits could potentially impact, if LocalTrait is sealed. (Exactly what the rules would be I don't know, but there's an opportunity if we know that all the possible implementations for a trait are in the current crate.)