Closed
Description
If the wrapped iterator implements ExactSizeIterator
then Fuse
blindly delegates len()
to it. The underlying iterator may know its exact size but return spurious None
results anyway, on which Fuse
will stop iterating even though the source knows that there are elements left to iterate, meaning Fuse
will indicate that there are elements left but never return them.
The behavior was introduced in #37944 but didn't see any discussion.
struct Alternate {
state: i32,
}
impl Iterator for Alternate {
type Item = i32;
fn next(&mut self) -> Option<i32> {
let val = self.state;
self.state = self.state + 1;
if val % 2 == 0 && val <= 4 {
Some(val)
} else {
None
}
}
}
impl ExactSizeIterator for Alternate {
// We can easily calculate the remaining number of iterations.
fn len(&self) -> usize {
std::cmp::max(0, 3 - (self.state + 1) / 2) as usize
}
}
fn main() {
eprintln!("### regular");
let mut iter = Alternate { state: 0 };
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
eprintln!("### fused");
let mut iter = Alternate { state: 0 }.fuse();
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
dbg!(iter.len(), iter.next());
}