Open
Description
The iterator adaptor .chain()
and similar code uses a state flag that changes mid-loop; the compiler should recognize this and try to split it into two consecutive loops if possible.
Reproduction in code (playground)
pub fn visit_both(a: &[u32], b: &[u32], f: fn(u32)) {
for &elt in chain(a, b) {
f(elt)
}
}
/// this is a simplified version of std::iter::Chain
pub struct Chain<I> { front: bool, a: I, b: I }
fn chain<I>(a: I, b: I) -> Chain<I::IntoIter> where I: IntoIterator {
Chain { front: true, a: a.into_iter(), b: b.into_iter() }
}
impl<I> Iterator for Chain<I> where I: Iterator {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.front {
if let elt @ Some(_) = self.a.next() {
return elt;
}
self.front = false;
}
self.b.next()
}
}
Actual Behaviour
There is only one call
instruction in visit_both
's generated code, indicating the loop was not split.
Expected Behaviour
Generated code should be more similar to two consecutive loops.