How to resolve 'Vec<Peekable<dyn Iterator<Item = T>>> doesn't have a size known at compile-time'?

I’m working on a Cartesian power implementation for iterators. I’m running into a snag where I don’t seem able to store a vector of peekable copies of the iterator I’m passed. No matter how much I finagle with boxes and pointers, it doesn’t work due to Vec<Peekable<dyn Iterator<Item = T>>> not having a known size at compile time.

Any ideas for how to make this size be known at compile time? I really just need to be store a pointer to the vector, right? There’s no reason it can’t be created on the heap, is there?

Here’s what I have so far (ignore the next() implementation, that was just to test to see if I could store the iterator and correctly use it’s next function):

mod cartesian_power {
    use core::iter::Peekable;

    pub struct CartesianPower<T> {
        prototype: Box<dyn Iterator<Item = T>>,
        iters: Vec<Peekable<dyn Iterator<Item = T>>>,
    }

    impl<T> CartesianPower<T> {
        pub fn new<I>(vals: I, power: usize) -> CartesianPower<T>
        where
            I: IntoIterator<Item = T>,
            I: Clone,
            <I as IntoIterator>::IntoIter: 'static,
        {
            let iters = Vec::with_capacity(power);
            for _ in 0..power {
                iters.push(vals.clone().into_iter().peekable());
            }
            Self {
                prototype: Box::new(vals.into_iter()),
                iters: iters,
            }
        }

    }

    impl<T> Iterator for CartesianPower<T> {
        type Item = T;
        fn next(&mut self) -> Option<T> {
            self.prototype.next()
        }
    }
}

>Solution :

You cannot store a Vec<dyn Trait> (or Vec<Peekable<dyn Trait>>) directly, you have to use an indirection as each element can have a different size: Vec<Box<Peekable<dyn Iterator<Item = T>>>>.

However, since all iterators in your case are the same, you can use generics and avoid the performance hit of Box and dynamic dispatch:

pub struct CartesianPower<I: Iterator> {
    prototype: I,
    iters: Vec<Peekable<I>>,
}

impl<Iter: Iterator> CartesianPower<Iter> {
    pub fn new<I>(vals: I, power: usize) -> CartesianPower<Iter>
    where
        I: IntoIterator<IntoIter = Iter>,
        I: Clone,
        <I as IntoIterator>::IntoIter: 'static,
    {
        let mut iters = Vec::with_capacity(power);
        for _ in 0..power {
            iters.push(vals.clone().into_iter().peekable());
        }
        Self {
            prototype: vals.into_iter(),
            iters: iters,
        }
    }

}

impl<I: Iterator> Iterator for CartesianPower<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> {
        self.prototype.next()
    }
}

Leave a Reply