Repository: petgraph/petgraph (language: rust)

Issue:
Struct `petgraph::graph::Externals` does not implement Clone
### Summary

The iterator struct `Externals` seems to have missed some trait implementations that it could have, most critically Clone.

### Motivation

Some cases, like the `cycle`-iterator adapter requires, require the iterator to be Clone which would make using the `Externals` struct a bit easier if it had that trait.
Also adding the Debug trait might be good too.

### Details

I don't see any problems from just adding an auto-derive for it, since the internal `iter::Enumerate` already has Clone (and Debug) too.
It also has some other traits implemented, such as `DoubleEndedIterator`, `ExactSizeIterator` etc, but I'm not sure if implementing those is necessary or compatible with the future API.

I will try to make a fork and a pull request for the change at some point unless someone wants to do it before me.



Discussion / hints:
See this call https://github.com/petgraph/petgraph/pull/415#issuecomment-823391361 :)

Fix patch:
diff --git a/src/adj.rs b/src/adj.rs
index f25d7f1a6..0989b097f 100644
--- a/src/adj.rs
+++ b/src/adj.rs
@@ -29,6 +29,7 @@ impl (Iterator) for
 /// An Iterator over the indices of the outgoing edges from a node.
 ///
 /// It does not borrow the graph during iteration.
+#[derive(Debug, Clone)]
 struct OutgoingEdgeIndices <Ix> where { Ix: IndexType }
 item: EdgeIndex<Ix>,
 iter: std::iter::Map<std::iter::Zip<Range<usize>, std::iter::Repeat<NodeIndex<Ix>>>, fn((usize, NodeIndex<Ix>)) -> EdgeIndex<Ix>>,
@@ -50,6 +51,7 @@ type RowIter<'a, E, Ix> = std::slice::Iter<'a, WSuc<E, Ix>>;
 iterator_wrap! {
 impl (Iterator DoubleEndedIterator ExactSizeIterator) for
 /// An iterator over the indices of the neighbors of a node.
+#[derive(Debug, Clone)]
 struct Neighbors<'a, E, Ix> where { Ix: IndexType }
 item: NodeIndex<Ix>,
 iter: std::iter::Map<RowIter<'a, E, Ix>, fn(&WSuc<E, Ix>) -> NodeIndex<Ix>>,
@@ -92,6 +94,7 @@ impl<'a, E, Ix: IndexType> visit::EdgeRef for EdgeReference<'a, E, Ix> {
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct EdgeIndices<'a, E, Ix: IndexType> {
     rows: std::iter::Enumerate<std::slice::Iter<'a, Row<E, Ix>>>,
     row_index: usize,
@@ -127,6 +130,7 @@ impl<'a, E, Ix: IndexType> Iterator for EdgeIndices<'a, E, Ix> {
 iterator_wrap! {
     impl (Iterator DoubleEndedIterator ExactSizeIterator) for
     /// An iterator over all node indices in the graph.
+    #[derive(Debug, Clone)]
     struct NodeIndices <Ix> where {}
     item: Ix,
     iter: std::iter::Map<Range<usize>, fn(usize) -> Ix>,
@@ -531,6 +535,7 @@ impl<'a, Ix: IndexType, E> visit::IntoEdgeReferences for &'a List<E, Ix> {
 iterator_wrap! {
 impl (Iterator) for
 /// Iterator over the [`EdgeReference`] of the outgoing edges from a node.
+#[derive(Debug, Clone)]
 struct OutgoingEdgeReferences<'a, E, Ix> where { Ix: IndexType }
 item: EdgeReference<'a, E, Ix>,
 iter: SomeIter<'a, E, Ix>,
diff --git a/src/algo/dominators.rs b/src/algo/dominators.rs
index f7e42e47e..b94ee0f30 100644
--- a/src/algo/dominators.rs
+++ b/src/algo/dominators.rs
@@ -91,6 +91,7 @@ where
 }
 
 /// Iterator for a node's dominators.
+#[derive(Debug, Clone)]
 pub struct DominatorsIter<'a, N>
 where
     N: 'a + Copy + Eq + Hash,
@@ -115,6 +116,7 @@ where
 }
 
 /// Iterator for nodes dominated by a given node.
+#[derive(Debug, Clone)]
 pub struct DominatedByIter<'a, N>
 where
     N: 'a + Copy + Eq + Hash,
diff --git a/src/algo/mod.rs b/src/algo/mod.rs
index 3ab889852..7ef0ca4f5 100644
--- a/src/algo/mod.rs
+++ b/src/algo/mod.rs
@@ -641,6 +641,7 @@ where
 }
 
 /// An iterator producing a minimum spanning forest of a graph.
+#[derive(Debug, Clone)]
 pub struct MinSpanningTree<G>
 where
     G: Data + IntoNodeReferences,
diff --git a/src/csr.rs b/src/csr.rs
index 50a9ce290..0517fb375 100644
--- a/src/csr.rs
+++ b/src/csr.rs
@@ -505,6 +505,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct EdgeReferences<'a, E: 'a, Ty, Ix: 'a> {
     source_index: NodeIndex<Ix>,
     index: usize,
@@ -671,6 +672,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct NodeIdentifiers<Ix = DefaultIx> {
     r: Range<usize>,
     ty: PhantomData<Ix>,
diff --git a/src/data.rs b/src/data.rs
index 7bb541140..8ad353d8b 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -396,6 +396,7 @@ impl<N, E, I: ?Sized> ElementIterator<N, E> for I where I: Iterator<Item = Eleme
 /// See [`.filter_elements()`][1] for more information.
 ///
 /// [1]: trait.ElementIterator.html#method.filter_elements
+#[derive(Debug, Clone)]
 pub struct FilterElements<I, F> {
     iter: I,
     node_index: usize,
diff --git a/src/graph_impl/mod.rs b/src/graph_impl/mod.rs
index 138f10aa7..6270b84fb 100644
--- a/src/graph_impl/mod.rs
+++ b/src/graph_impl/mod.rs
@@ -1434,6 +1434,7 @@ where
 }
 
 /// An iterator over either the nodes without edges to them or from them.
+#[derive(Debug, Clone)]
 pub struct Externals<'a, N: 'a, Ty, Ix: IndexType = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Node<N, Ix>>>,
     dir: Direction,
@@ -1475,6 +1476,7 @@ where
 /// [1]: struct.Graph.html#method.neighbors
 /// [2]: struct.Graph.html#method.neighbors_directed
 /// [3]: struct.Graph.html#method.neighbors_undirected
+#[derive(Debug)]
 pub struct Neighbors<'a, E: 'a, Ix: 'a = DefaultIx> {
     /// starting node to skip over
     skip_start: NodeIndex<Ix>,
@@ -1596,6 +1598,7 @@ where
 }
 
 /// Iterator over the edges of from or to a node
+#[derive(Debug)]
 pub struct Edges<'a, E: 'a, Ty, Ix: 'a = DefaultIx>
 where
     Ty: EdgeType,
@@ -1680,6 +1683,7 @@ where
 }
 
 /// Iterator over the multiple directed edges connecting a source node to a target node
+#[derive(Debug, Clone)]
 pub struct EdgesConnecting<'a, E: 'a, Ty, Ix: 'a = DefaultIx>
 where
     Ty: EdgeType,
@@ -1730,8 +1734,9 @@ where
 }
 
 /// Iterator yielding mutable access to all node weights.
+#[derive(Debug)]
 pub struct NodeWeightsMut<'a, N: 'a, Ix: IndexType = DefaultIx> {
-    nodes: ::std::slice::IterMut<'a, Node<N, Ix>>,
+    nodes: ::std::slice::IterMut<'a, Node<N, Ix>>, // TODO: change type to something that implements Clone?
 }
 
 impl<'a, N, Ix> Iterator for NodeWeightsMut<'a, N, Ix>
@@ -1750,8 +1755,9 @@ where
 }
 
 /// Iterator yielding mutable access to all edge weights.
+#[derive(Debug)]
 pub struct EdgeWeightsMut<'a, E: 'a, Ix: IndexType = DefaultIx> {
-    edges: ::std::slice::IterMut<'a, Edge<E, Ix>>,
+    edges: ::std::slice::IterMut<'a, Edge<E, Ix>>, // TODO: change type to something that implements Clone?
 }
 
 impl<'a, E, Ix> Iterator for EdgeWeightsMut<'a, E, Ix>
@@ -2059,6 +2065,7 @@ where
 }
 
 /// Iterator over all nodes of a graph.
+#[derive(Debug, Clone)]
 pub struct NodeReferences<'a, N: 'a, Ix: IndexType = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Node<N, Ix>>>,
 }
@@ -2129,6 +2136,7 @@ where
 }
 
 /// Iterator over all edges of a graph.
+#[derive(Debug, Clone)]
 pub struct EdgeReferences<'a, E: 'a, Ix: IndexType = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Edge<E, Ix>>>,
 }
diff --git a/src/graph_impl/stable_graph/mod.rs b/src/graph_impl/stable_graph/mod.rs
index fc45c5f4f..352b8a786 100644
--- a/src/graph_impl/stable_graph/mod.rs
+++ b/src/graph_impl/stable_graph/mod.rs
@@ -1265,6 +1265,7 @@ where
 }
 
 /// Iterator over all nodes of a graph.
+#[derive(Debug, Clone)]
 pub struct NodeReferences<'a, N: 'a, Ix: IndexType = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
 }
@@ -1379,6 +1380,7 @@ where
 }
 
 /// Iterator over the edges of from or to a node
+#[derive(Debug, Clone)]
 pub struct Edges<'a, E: 'a, Ty, Ix: 'a = DefaultIx>
 where
     Ty: EdgeType,
@@ -1492,6 +1494,7 @@ where
 }
 
 /// Iterator over all edges of a graph.
+#[derive(Debug, Clone)]
 pub struct EdgeReferences<'a, E: 'a, Ix: 'a = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Edge<Option<E>, Ix>>>,
 }
@@ -1529,6 +1532,7 @@ where
 }
 
 /// An iterator over either the nodes without edges to them or from them.
+#[derive(Debug, Clone)]
 pub struct Externals<'a, N: 'a, Ty, Ix: IndexType = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
     dir: Direction,
@@ -1564,6 +1568,7 @@ where
 /// Iterator over the neighbors of a node.
 ///
 /// Iterator element type is `NodeIndex`.
+#[derive(Debug, Clone)]
 pub struct Neighbors<'a, E: 'a, Ix: 'a = DefaultIx> {
     /// starting node to skip over
     skip_start: NodeIndex<Ix>,
@@ -1695,6 +1700,7 @@ impl<Ix: IndexType> WalkNeighbors<Ix> {
 }
 
 /// Iterator over the node indices of a graph.
+#[derive(Debug, Clone)]
 pub struct NodeIndices<'a, N: 'a, Ix: 'a = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
 }
@@ -1748,6 +1754,7 @@ where
 }
 
 /// Iterator over the edge indices of a graph.
+#[derive(Debug, Clone)]
 pub struct EdgeIndices<'a, E: 'a, Ix: 'a = DefaultIx> {
     iter: iter::Enumerate<slice::Iter<'a, Edge<Option<E>, Ix>>>,
 }
diff --git a/src/graphmap.rs b/src/graphmap.rs
index e7ae3069f..8cc5b5f2e 100644
--- a/src/graphmap.rs
+++ b/src/graphmap.rs
@@ -480,11 +480,13 @@ where
 
 iterator_wrap! {
     impl (Iterator DoubleEndedIterator ExactSizeIterator) for
+    #[derive(Debug, Clone)]
     struct Nodes <'a, N> where { N: 'a + NodeTrait }
     item: N,
     iter: Cloned<Keys<'a, N, Vec<(N, CompactDirection)>>>,
 }
 
+#[derive(Debug, Clone)]
 pub struct Neighbors<'a, N, Ty = Undirected>
 where
     N: 'a,
@@ -511,6 +513,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct NeighborsDirected<'a, N, Ty>
 where
     N: 'a,
@@ -547,6 +550,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct Edges<'a, N, E: 'a, Ty>
 where
     N: 'a + NodeTrait,
@@ -587,6 +591,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct AllEdges<'a, N, E: 'a, Ty>
 where
     N: 'a + NodeTrait,
@@ -644,7 +649,7 @@ pub struct AllEdgesMut<'a, N, E: 'a, Ty>
 where
     N: 'a + NodeTrait,
 {
-    inner: IndexMapIterMut<'a, (N, N), E>,
+    inner: IndexMapIterMut<'a, (N, N), E>, // TODO: change to something that implements Debug + Clone?
     ty: PhantomData<Ty>,
 }
 
@@ -833,6 +838,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct NodeIdentifiers<'a, N, E: 'a, Ty>
 where
     N: 'a + NodeTrait,
@@ -870,6 +876,7 @@ where
     }
 }
 
+#[derive(Debug, Clone)]
 pub struct NodeReferences<'a, N, E: 'a, Ty>
 where
     N: 'a + NodeTrait,
diff --git a/src/matrix_graph.rs b/src/matrix_graph.rs
index 2fdbfc137..d3106d48f 100644
--- a/src/matrix_graph.rs
+++ b/src/matrix_graph.rs
@@ -544,6 +544,7 @@ impl<N, E, Null: Nullable<Wrapped = E>, Ix: IndexType> MatrixGraph<N, E, Directe
 ///
 /// [1]: ../visit/trait.IntoNodeIdentifiers.html#tymethod.node_identifiers
 /// [2]: struct.MatrixGraph.html
+#[derive(Debug, Clone)]
 pub struct NodeIdentifiers<'a, Ix> {
     iter: IdIterator<'a>,
     ix: PhantomData<Ix>,
@@ -572,6 +573,7 @@ impl<'a, Ix: IndexType> Iterator for NodeIdentifiers<'a, Ix> {
 ///
 /// [1]: ../visit/trait.IntoNodeReferences.html#tymethod.node_references
 /// [2]: struct.MatrixGraph.html
+#[derive(Debug, Clone)]
 pub struct NodeReferences<'a, N: 'a, Ix> {
     nodes: &'a IdStorage<N>,
     iter: IdIterator<'a>,
@@ -604,6 +606,7 @@ impl<'a, N: 'a, Ix: IndexType> Iterator for NodeReferences<'a, N, Ix> {
 ///
 /// [1]: ../visit/trait.IntoEdgeReferences.html#tymethod.edge_references
 /// [2]: struct.MatrixGraph.html
+#[derive(Debug, Clone)]
 pub struct EdgeReferences<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> {
     row: usize,
     column: usize,
@@ -669,6 +672,7 @@ impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator
 ///
 /// [1]: struct.MatrixGraph.html#method.neighbors
 /// [2]: struct.MatrixGraph.html#method.neighbors_directed
+#[derive(Debug, Clone)]
 pub struct Neighbors<'a, Ty: EdgeType, Null: 'a + Nullable, Ix>(Edges<'a, Ty, Null, Ix>);
 
 impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Neighbors<'a, Ty, Null, Ix> {
@@ -679,6 +683,7 @@ impl<'a, Ty: EdgeType, Null: Nullable, Ix: IndexType> Iterator for Neighbors<'a,
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 enum NeighborIterDirection {
     Rows,
     Columns,
@@ -690,6 +695,7 @@ enum NeighborIterDirection {
 ///
 /// [1]: struct.MatrixGraph.html#method.edges
 /// [2]: struct.MatrixGraph.html#method.edges_directed
+#[derive(Debug, Clone)]
 pub struct Edges<'a, Ty: EdgeType, Null: 'a + Nullable, Ix> {
     iter_direction: NeighborIterDirection,
     node_adjacencies: &'a [Null],
@@ -844,7 +850,7 @@ fn ensure_len<T: Default>(v: &mut Vec<T>, size: usize) {
     }
 }
 
-#[derive(Clone)]
+#[derive(Debug, Clone)]
 struct IdStorage<T> {
     elements: Vec<Option<T>>,
     upper_bound: usize,
@@ -920,6 +926,7 @@ impl<T> IndexMut<usize> for IdStorage<T> {
     }
 }
 
+#[derive(Debug, Clone)]
 struct IdIterator<'a> {
     upper_bound: usize,
     removed_ids: &'a IndexSet<usize>,
diff --git a/src/visit/filter.rs b/src/visit/filter.rs
index 110ebea25..4fb921f4a 100644
--- a/src/visit/filter.rs
+++ b/src/visit/filter.rs
@@ -106,6 +106,7 @@ where
 }
 
 /// A filtered neighbors iterator.
+#[derive(Debug, Clone)]
 pub struct NodeFilteredNeighbors<'a, I, F: 'a> {
     include_source: bool,
     iter: I,
@@ -176,6 +177,7 @@ where
 }
 
 /// A filtered node references iterator.
+#[derive(Debug, Clone)]
 pub struct NodeFilteredNodes<'a, I, F: 'a> {
     include_source: bool,
     iter: I,
@@ -216,6 +218,7 @@ where
 }
 
 /// A filtered edges iterator.
+#[derive(Debug, Clone)]
 pub struct NodeFilteredEdgeReferences<'a, G, I, F: 'a> {
     graph: PhantomData<G>,
     iter: I,
@@ -253,6 +256,7 @@ where
 }
 
 /// A filtered edges iterator.
+#[derive(Debug, Clone)]
 pub struct NodeFilteredEdges<'a, G, I, F: 'a> {
     graph: PhantomData<G>,
     include_source: bool,
@@ -381,6 +385,7 @@ where
 }
 
 /// A filtered neighbors iterator.
+#[derive(Debug, Clone)]
 pub struct EdgeFilteredNeighbors<'a, G, F: 'a>
 where
     G: IntoEdges,
@@ -441,6 +446,7 @@ where
 }
 
 /// A filtered edges iterator.
+#[derive(Debug, Clone)]
 pub struct EdgeFilteredEdges<'a, G, I, F: 'a> {
     graph: PhantomData<G>,
     iter: I,
@@ -461,6 +467,7 @@ where
 }
 
 /// A filtered neighbors-directed iterator.
+#[derive(Debug, Clone)]
 pub struct EdgeFilteredNeighborsDirected<'a, G, F: 'a>
 where
     G: IntoEdgesDirected,
diff --git a/src/visit/reversed.rs b/src/visit/reversed.rs
index e2e3d9f16..9b3cd7e8c 100644
--- a/src/visit/reversed.rs
+++ b/src/visit/reversed.rs
@@ -76,6 +76,7 @@ impl<G: Visitable> Visitable for Reversed<G> {
 }
 
 /// A reversed edges iterator.
+#[derive(Debug, Clone)]
 pub struct ReversedEdges<I> {
     iter: I,
 }
@@ -143,6 +144,7 @@ where
 }
 
 /// A reversed edge references iterator.
+#[derive(Debug, Clone)]
 pub struct ReversedEdgeReferences<I> {
     iter: I,
 }


Test patch: