The GroupbyApply for GroupbyOrdered
can be fixed by having functionality at the single lifetime level...
pub trait SliceIndexGat<'a, Guard = &'a Self> {
type Output;
fn slice_index_gat(&'a self, range: std::ops::Range<usize>) -> Self::Output;
}
pub trait SliceIndex: for<'a> SliceIndexGat<'a> {
fn slice_index(&self, range: std::ops::Range<usize>) -> <Self as SliceIndexGat<'_>>::Output;
}
impl<S: for<'a> SliceIndexGat<'a>> SliceIndex for S {
#[inline]
fn slice_index(&self, range: std::ops::Range<usize>) -> <Self as SliceIndexGat<'_>>::Output {
self.slice_index_gat(range)
}
}
...and then working at a single level in the implementation:
impl<'a, I, T, E> GroupbyApply<&'a I, E> for GroupbyOrdered<T>
where
I: ?Sized + SliceIndexGat<'a, Output = E> + 'a,
{
fn apply<F, N>(&self, data: &'a I, f: F) -> Vec<N>
where
F: Fn(E) -> N,
{
self.index
.iter()
.map(|x| {
let data_part = data.slice_index_gat(x.clone());
f(data_part)
})
.collect_vec()
}
}
(partial fix)
But the GroupbyApply for GroupbyUnOrdered
is trickier because you do actually need a HRTB as written, and that's causing problems for you here:
impl<'a, I, E, T, I2> GroupbyApply<&'a I, E> for GroupbyUnOrdered<T>
where
I: UniqueForTuple<Output = I2> + ?Sized,
GroupbyOrdered<T>: for<'b> GroupbyApply<&'b I2, E>,
// ^^^^^^^ ^
Because E
might be different based on 'b
, but you're requiring that E
is the same for all &'b I2
.
Based on the implementations, it feels like the parameters on GroupByApply
are meant to be type constructors, like GATs. I tried a couple approaches that were stymied by E
being a type parameter. Even if they had worked, though, they were pretty ugly and I'd be surprised if they didn't confuse inference. So I'm going to stop poking at that for now.
If you only need a fixed set of types or type constructors, giving up on being as general as possible with traits may be a better way to go. For example if the definition of some GAT is always a reference, just use references.
If you don't know why it helps you and can't explain why it's sound, the answer to this question is no.