Unable to get an iterator on generic struct working

Consider the code here (playground):

use std::ops::Mul;

/// A vector of numeric types that returns the number 
/// and it's double on iteration.
#[derive(Debug)]
struct DoublePairVec<T: Mul> {
    numbers: Vec<T>
}



impl<T> Iterator for DoublePairVec<T>
where T: Mul<Output = T> + Copy
{
    type Item = (T, T);
    
    fn next(&mut self) -> Option<self::Item> {
        match self.numbers.iter().next() {
            Some(n) => Some((n, *n * 2 as T)),
            _ => None
        }
    }
}


pub fn main() {
    let feed: DoublePairVec<u32> = DoublePairVec{numbers: vec![]};
    feed.numbers.push(2);
    feed.numbers.push(3);
    feed.numbers.push(4);
    for pair in feed {
        println!("{:?}", pair);
    }
}

I am stuck at the following error:

   Compiling playground v0.0.1 (/playground)
error[E0412]: cannot find type `Item` in module `self`
  --> src/main.rs:15:40
   |
15 |     fn next(&mut self) -> Option<self::Item> {
   |                                        ^^^^ not found in `self`
help: possible candidates are found in other modules, you can import them into scope
   |
1  | use chrono::format::Item;
   |
1  | use syn::Item;
   |

error[E0605]: non-primitive cast: `{integer}` as `T`

I am just stuck with no idea how to proceed. Tried reading more about Associated Types in the book but no leads.

You have a couple of errors. The one you saw is that it should actually be Self::Item not self::Item. The self you see for example in fn next(&mut self) is actually sugar for self: &mut Self where Self is the type and self is just the name of the parameter. Item is defined on the type Self therefore we write Self::Item.
If you fix that there are a couple of other issues the biggest one being that you cant use as to cast to a generic T. You can solve this in one of two ways either introduce a From bound or simply use n+n instead of n*2. If you fix all the remaining problems you get the following compiling
playground which still has a logic bug I will let you sort this one out yourself.

1 Like

Thanks! Really silly mistake at my end. :disappointed:

About the logic bug, your reference is to the child iterator getting initialised on each run of next() in the line below?

/// self.numbers.iter().next() will always return the first item
/// and therefore never terminate
match self.numbers.iter().next() {.....}

Exactly. You basically have two choices implement IntoIterator on DoublePairVec or &DoublePairVec or you store a IntoIter instead of a Vec inside of DoublePairVec.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.