I have a CombinedIterator struct which contains a vec of peekable iterators. I'm trying to implement Iterator on this struct such that the minimum next elements from the component iterators is returned.
Here's one impl attempt:
struct CombinedIterator<T> {
iters: Vec<Peekable<Box<dyn Iterator<Item = T>>>>,
}
impl<T: Ord> Iterator for CombinedIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iters
.iter_mut()
.filter_map(|itr| itr.peek().map(|peeked| (peeked, itr)))
.min_by(|x, y| x.0.cmp(y.0))
.map(|(_, itr)| itr.next().unwrap())
}
}
Which fails to compile:
error[E0505]: cannot move out of `itr` because it is borrowed
--> examples/combined_iter.rs:13:46
|
13 | .filter_map(|itr| itr.peek().map(|peeked| (peeked, itr)))
| - ---------------^^^^^^^^---------------
| | | | |
| | | | move occurs due to use in closure
| | | move out of `itr` occurs here
| | borrow of `*itr` occurs here
| | returning this value requires that `*itr` is borrowed for `'1`
| return type of closure is Option<(&'1 T, &mut Peekable<Box<dyn Iterator<Item = T>>>)>
I know there are other (possibly superior) ways to implement next() to avoid this issue, but I'd like to understand why this impl fails.
The compiler error doesn't make sense to me. As input to the closure, itr is already borrowed as type &mut Peekable<_> so I don't understand why the compiler is saying further borrowing occurs. Why can't the same mutably borrowed itr reference be used for both itr.peek() and as the return value in the tuple?