rfcs
rfcs copied to clipboard
Move SliceIndex type parameter to parameters
If I have a struct like this:
struct T1 {}
struct T2 {}
pub struct Aggregate {
v1: Vec<T1>,
v2: Vec<T2>,
}
impl Aggregate {
pub fn compute<R>(&self, range: R) -> Option<u32> {
for v in self.v1.get(range)? {
output += v.compute();
}
for v in self.v2.get(range)? {
output += v.compute();
}
Some(output)
}
}
The type bound for R would need to be R: SliceIndex<[T1]> + SliceIndex<[T2]>, which exposes internal implementation details.
I propose moving the <T> in SliceIndex<T> to the methods and leverage GATs:
trait SliceIndex : Sized {
type Output<T: ?Sized>: ?Sized;
fn get<T: ?Sized>(self, slice: &T) -> Option<&Self::Output<T>>;
fn get_mut<T: ?Sized>(self, slice: &mut T) -> Option<&mut Self::Output<T>>;
// ...
}
How could you remove the type parameter without breaking backwards compatibility? This compiles on stable:
fn it_is_stable(_: impl std::slice::SliceIndex<i32>) {}
Currently the trait is sealed, so the usage pattern is quite limited. Can we do something in an edition change to remove the unnecessary type bounds somehow? Or just accept an unused type bound? Probably wouldn't work with impl SliceIndex<[i32], Output = [i32]> though.
Currently the trait is sealed, so the usage pattern is quite limited. Can we do something in an edition change to remove the unnecessary type bounds somehow?
No.
Or just accept an unused type bound?
I believe that accepting completely unused parameters would allow imposing incorrect constraints on implementations which would be unsound. In general there is no good reason to do this.
The only way forward for this, realistically, is implementing a new SliceIndex trait, or finding a solution that is actually backwards-compatible.