I tried this code:
fn main() {
let a = vec![String::new(), String::new()];
let b = [()];
let mut counter = 0;
a.into_iter()
.map(|i| {
counter += 1;
i
})
.zip(&b)
.zip(&b)
.for_each(drop);
assert_eq!(counter, 2);
let a = vec![String::new(), String::new()];
let b = [()];
let mut counter = 0;
a.iter()
.map(|i| {
counter += 1;
i
})
.zip(&b)
.zip(&b)
.for_each(drop);
assert_eq!(counter, 2); // this fails, even though it succeed in the non-specialized version
}
Playground link
I would expect the two iterators to behave the same, so either both asserts fail (actually the first should stop the program) or neither of them. Instead, the second iterator doesn't preserve side-effects. causing the second assert (and only that one) to fail.
I don't think there's a way to solve this without completly changing the TrustedRandomAccess trait to use some type level trickery to replace may_have_side_effect. I wonder if there's even a point to keep the simulated side effects in the specialized ZipImpl::next if it doesn't cover all cases.
I tried this code:
Playground link
I would expect the two iterators to behave the same, so either both asserts fail (actually the first should stop the program) or neither of them. Instead, the second iterator doesn't preserve side-effects. causing the second assert (and only that one) to fail.
I don't think there's a way to solve this without completly changing the
TrustedRandomAccesstrait to use some type level trickery to replacemay_have_side_effect. I wonder if there's even a point to keep the simulated side effects in the specializedZipImpl::nextif it doesn't cover all cases.