Pass a boxed iterator to a function

Hello, I have the following struct:

pub struct DotBuilder<'a> {
    graph: &'a Graph,
    graph_name: String,
    nodes: Box<Iterator<Item = &'a NodeRef> + 'a>,
    edges: &'a Edges

And the following method:

// Inside DotBuilder
fn nodes_str<'b, I>(nodes: I) -> Vec<String> 
        I: IntoIterator<Item = &'b NodeRef> {

Then I try to use it:

// Another function inside DotBuilder
let nodes_str = Self::nodes_str(self.nodes);

But I get the following error:

error[E0507]: cannot move out of self.nodes which is behind a shared reference
--> src/graph_engine/model/
317 | let nodes_str = Self::nodes_str(self.nodes);
| ^^^^^^^^^^ move occurs because self.nodes has type std::boxed::Box<dyn std::iter::Iterator<Item = &graph_engine::model::node::NodeRef>>, which does not implement the Copy trait

And I don't know how to pass my iterator inside a box to my function. Because I still want my function to be called with classic iterators too...

You're probably running this code in a method with &self (shared borrow), but it has to take self (owned).

Box always has a single owner, so passing it somewhere means old owner can't use it any more. If it's owned by a struct, it means you have to destroy the struct in order to get the Box out of it. But if you only have a shared immutable reference to a struct, you're not allowed to destroy it, so you're not allowed to tear Box out of it.

So you can only pass the Box inside a method that takes self and destroys DotBuilder in the process.

Things to keep in mind:

  • Iterators have to be mutated to be used. Immutable Iterator reference is absolutely useless, as it won't be allowed to give any elements.
  • Iterators are one-time-use only. You can't restart them. Once you iterate to the end of the iterator, it's done and can't be used any more.

If you did not mean destroying whole DotBuilder to have one-time access to nodes, then you may want to store nodes as &[NodeRef] or have something else (a method/trait/iterator-generator object) that creates a new iterator instance every time you ask for it.

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.