I believe that this should work, because the compiler knows that the SliceIndex::Output associated types are distinct from each other, which means that the implementations cannot overlap in practice, i.e. no type I can implement SliceIndex<[T]> with two different output types, so only one of these impls will ever apply for any choice of the type parameters T and I:
impl<T,I:SliceIndex<[T], Output=[T]>> IndexMut<I> for CachedSlice<T> {
fn index_mut(&mut self, idx:I)->&mut [T] {
let slice = &mut self.cpu[idx];
// Update self.dirty
slice
}
}
impl<T,I:SliceIndex<[T], Output=T>> IndexMut<I> for CachedSlice<T> {
fn index_mut(&mut self, idx:I)->&mut T {
let item = &mut self.cpu[idx];
// Update self.dirty
item
}
}
Unfortunately, the compiler doesn't agree . Other than a concrete implementation for every possible index type, is there a way to make this work?
Disjointness based on associated types RFC (closed). I recommend reading the comments, and maybe even some of the linked issues, to anyone interested in the concerns and difficulties around negative reasoning, exclusive traits, and the like.
There's a work around explored in the last comment, and here's another. I believe they are the same or similar to each other and to your workaround above, but didn't take the time to actually compare and contrast them.