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.

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.