I still think Custom DST is the proper backward-compatible solution here rather than GATs, due to the problems pointed out by @CAD97. You place the view information into the metadata part of the DST.
Referring to the linked thread, we can define the output type as this collapsed block.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct ColumnMeta {
stride: usize,
len: usize,
}
// "treat `&Column<T>` like `(*const T, ColumnMeta)` ≈ `(*const T, usize, usize)`"
pub dyn type Column<T>(regular: ColumnMeta) = [T];
impl<T> dst::Regular for Column<T> {
fn reduce_with_metadata(meta: ColumnMeta) -> usize {
meta.len
}
}
impl<T> Index<usize> for LazyTransposedMatrix<T> {
type Output = Column<T>;
fn index(&self, col_index: usize) -> &Self::Output {
assert!(col_index < self.width);
// urgh.
unsafe {
&*<*const Row<T>>::from_raw_parts(
self.base.as_ptr().add(col_index),
ColumnMeta {
stride: self.width,
len: self.width * (self.height - 1) + 1,
},
)
}
}
}
impl<T> Index<usize> for Column<T> {
type Output = T;
fn index(&self, row_index: usize) -> &Self::Output {
let meta = ptr::metadata(self);
let slice = dst::reduce(self);
&slice[row_index * meta.stride]
}
}