How can I avoid GATs in this code?

I am trying to use the following "extracted architecture" in a larger project. I'm using GATs, and I see no easy way to work around them. This snippet works, but I slip on ICE constantly when taking this architecture to the larger project. Any pointers for avoiding generic_associated_types, and preferably also type_alias_impl_trait?

#![allow(incomplete_features)]
#![feature(type_alias_impl_trait)]
#![feature(generic_associated_types)]

use core::marker::PhantomData;

////////////////////////////////////////////////////////////////////////////////

trait SparseColumnGenerator {
    type NT;
    type MySparseColumn<'a>: SparseColumn<'a, Self::NT>;

    fn generate_column<'a>(&'a self) -> Self::MySparseColumn<'a>;
}
trait SparseColumn<'a, NT: 'a>
where
    for<'r> &'r Self: IntoIterator<Item = &'a (usize, NT)>,
{
}

////////////////////////////////////////////////////////////////////////////////

struct IGenerateSparseColumns<NT>(Vec<(usize, NT)>);
impl<NT: 'static> SparseColumnGenerator for IGenerateSparseColumns<NT> {
    type NT = NT;
    type MySparseColumn<'a> = IAmAColumn<'a, NT, impl Iterator<Item = &'a (usize, NT)> + Clone>;
    
    fn generate_column<'a>(&'a self) -> Self::MySparseColumn<'a> {
        IAmAColumn(self.0.iter().filter(|&(i, _)| i % 2 == 0))
    }
}

struct IAmAColumn<'a, NT: 'a, I: Iterator<Item = &'a (usize, NT)>>(I);
impl<'a, NT: 'a, I: 'a + Iterator<Item = &'a (usize, NT)> + Clone> SparseColumn<'a, NT> for IAmAColumn<'a, NT, I> {
}
impl<'a, NT, I: Iterator<Item = &'a (usize, NT)> + Clone> IntoIterator for &IAmAColumn<'a, NT, I> {
    type Item = &'a (usize, NT);
    type IntoIter = impl Iterator<Item = Self::Item>;
    
    fn into_iter(self) -> Self::IntoIter {
        self.0.clone().filter(|&(i, _)| i % 4 == 0).clone()
    }
}

////////////////////////////////////////////////////////////////////////////////

trait InverseMaintenance<'data> {
    type InnerNT;

    fn compute<NT: 'data, C>(&self, column: C) -> Self::InnerNT
    where
        &'data NT: Into<Self::InnerNT>,
        C: SparseColumn<'data, NT>,
        for<'r> &'r C: IntoIterator<Item = &'data (usize, NT)>,
    ;
}
struct IMaintainInverse<NT>(PhantomData<NT>);
impl<'data, InnerNT> InverseMaintenance<'data> for IMaintainInverse<InnerNT> {
    type InnerNT = InnerNT;

    fn compute<NT: 'data, C>(&self, column: C) -> InnerNT 
    where
        &'data NT: Into<InnerNT>,
        C: SparseColumn<'data, NT>,
        for<'r> &'r C: IntoIterator<Item = &'data (usize, NT)>,
    {
        let x = &column;
        for (_, y) in x {
            return y.into();
        }
        panic!();
    }
}

////////////////////////////////////////////////////////////////////////////////

fn main() {
    let data = IGenerateSparseColumns(vec![(3, 0), (8, 1), (10, 2), (99, 3)]);
    let x = data.generate_column();
    
    for z in &x {
        let (_, y) = z;
        println!("{}", y);
    }
    for y in &x {
        println!("{:?}", y);
    }
    
    let a = IMaintainInverse(Default::default());
    let result: &i32 = a.compute(x);
    println!("{}", result);
}

Playground

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.