Unconstrained type parameter implementing IntoIterator

108 views Asked by At

How do I implement IntoIterator with a generic type parameter without getting into this kind of error, I think is the same error than here but the solution proposed there is not valid in this context, also doing a method called iter on Counter would solve the issue but it won't be idiomatic

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Id(u32);

struct Counter {
    top: u32
}

struct Iter<R: Iterator<Item = Id>>(R);  

impl<R> Iterator for Iter<R>
where
    R: Iterator<Item = Id> 
{
    type Item = Id;
    
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

// Unconstrained type parameter `I`
impl<I> IntoIterator for Counter 
where
    I: Iterator<Item = Id>
{
    type Item = Id;
    type IntoIter = I;

    fn into_iter(self) -> Self::IntoIter {
        Iter(0..self.top)
    }
}

This is the behaviour I expect from the implementation.

fn main() {
    let mut counter = Counter { top: 3 };
    assert_eq!(
        counter.into_iter().collect::<Vec<Id>>(),
        vec![Id(0), Id(1), Id(2)]
    );
}

Link to playground

1

There are 1 answers

0
Dogbert On BEST ANSWER

This can be solved without needing the I type parameter:

struct Iter<R: Iterator<Item = u32>>(R);

impl<R> Iterator for Iter<R>
where
    R: Iterator<Item = u32>,
{
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(Id)
    }
}

impl IntoIterator for Counter {
    type Item = Id;
    type IntoIter = Iter<std::ops::Range<u32>>;

    fn into_iter(self) -> Self::IntoIter {
        Iter(0..self.top)
    }
}

Playground