Providing iteration for enum

I have a enum wrapping a vector of traits and I am trying to allow
iterating a PointGroup and provide .iter() etc

However, I get the error below that I don't understand.

error[E0599]: the method `next` exists for mutable reference `&mut Vec<Box<(dyn Point + 'static)>>`, but its trait bounds were not satisfied
pub trait Point: Send + Sync + core::fmt::Debug {
    fn name(&self) -> String;
}

#[derive(Clone, Debug)]
pub struct MyPoint {
    name: String    
}

impl MyPoint {
    pub fn new(n: &str) -> Box<Self> {
        Box::new(MyPoint {name: n.to_string()})
    }
}

impl Point for MyPoint {
    fn name(&self) -> String {
        self.name.to_string()
    }
}

pub enum PointGroup {
    DefinedPointGroup(Vec<Box<dyn Point>>),
    ImplicitPointGroup
}

impl Iterator for PointGroup {
    type Item = Box<dyn Point>;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            PointGroup::DefinedPointGroup(iter) => {
                iter.next()
            }
            PointGroup::ImplicitPointGroup => {
                None
            }
        }
    }
}


fn main() {
    
    let points: Vec<Box<dyn Point>> = vec![MyPoint::new("one"), MyPoint::new("two"), MyPoint::new("three")];
    let point_group = PointGroup::DefinedPointGroup(points);
    
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0599]: the method `next` exists for mutable reference `&mut Vec<Box<(dyn Point + 'static)>>`, but its trait bounds were not satisfied
  --> src/main.rs:33:22
   |
33 |                 iter.next()
   |                      ^^^^ method cannot be called on `&mut Vec<Box<(dyn Point + 'static)>>` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `Vec<Box<(dyn Point + 'static)>>: Iterator`
           which is required by `&mut Vec<Box<(dyn Point + 'static)>>: Iterator`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` due to previous error

You need to make an IntoIter to hold the iterator over your vec (not impl Iterator directly onto your enum):

pub enum PointGroupIter {
    DefinedPointGroup(std::vec::IntoIter<Box<dyn Point>>),
    ImplicitPointGroup
}

impl IntoIterator for PointGroup {
    type IntoIter = PointGroupIter;
    type Item = Box<dyn Point>;
    fn into_iter(self) -> Self::IntoIter {
        match self {
            PointGroup::DefinedPointGroup(list) => PointGroupIter::DefinedPointGroup(list.into_iter()),
            PointGroup::ImplicitPointGroup => PointGroupIter::ImplicitPointGroup,
        }
    }
}

impl Iterator for PointGroupIter {
    type Item = Box<dyn Point>;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            PointGroupIter::DefinedPointGroup(iter) => {
                iter.next()
            }
            PointGroupIter::ImplicitPointGroup => {
                None
            }
        }
    }
}

Something vaguely like that. Though you should probably get out of your enum and iterate over the vec.

2 Likes

Thanks. Still had trouble.

On reflection I think I agree about getting the vec out of the enum. It's not worth the readability improvements to implement this.