Closed
Description
Scan
unconditionally implements FusedIterator
if the wrapped iterator does:
impl<B, I, St, F> FusedIterator for Scan<I, St, F>
where I: FusedIterator, F: FnMut(&mut St, I::Item) -> Option<B> {}
Since the closure to scan
can choose to return None
, this implementation is overly broad. It would need to take the closure into account, which seems... not possible.
Here's a reproduction showing the unexpected behavior when the closure returns None
:
#![feature(fused)]
fn dump<I: Iterator<Item = i32>>(label: &str, mut iter: I) {
println!("= Running: {}", label);
for _ in 0..10 {
println!("{:?}", iter.next());
}
println!("");
}
fn boxed_internal_fuse() -> Box<Iterator<Item = i32>> {
Box::new((1..3)
.scan(1, |_, x| if x < 2 { None } else { Some(x) })
.fuse())
}
fn boxed_no_fuse() -> Box<Iterator<Item = i32>> {
Box::new((1..3)
.scan(1, |_, x| if x < 2 { None } else { Some(x) }))
}
use std::iter::FusedIterator;
fn boxed_no_fuse_but_fused() -> Box<FusedIterator<Item = i32>> {
Box::new((1..3)
.scan(1, |_, x| if x < 2 { None } else { Some(x) }))
}
fn main() {
let i1 = (1..3)
.scan(1, |_, x| if x < 2 { None } else { Some(x) });
dump("Scan", i1);
let i2 = (1..3)
.scan(1, |_, x| if x < 2 { None } else { Some(x) })
.fuse();
dump("Fuse<Scan>", i2);
dump("Box<Fuse<Scan>>", boxed_internal_fuse());
dump("Fuse<Box<Iterator>>", boxed_no_fuse().fuse());
dump("Fuse<Box<FusedIterator>>", boxed_no_fuse_but_fused().fuse());
}
= Running: Scan
None
Some(2)
None
None
None
None
None
None
None
None
= Running: Fuse<Scan>
None
Some(2)
None
None
None
None
None
None
None
None
= Running: Box<Fuse<Scan>>
None
Some(2)
None
None
None
None
None
None
None
None
= Running: Fuse<Box<Iterator>>
None
None
None
None
None
None
None
None
None
None
= Running: Fuse<Box<FusedIterator>>
None
Some(2)
None
None
None
None
None
None
None
None
This example requires nightly for the feature to demonstrate, but the effect can be felt in stable Rust.
Metadata
Metadata
Assignees
Labels
No labels