pub struct Zip<A, B> {
a: A,
b: B,
- // index and len are only used by the specialized version of zip
+ // index, len and a_len are only used by the specialized version of zip
index: usize,
len: usize,
+ a_len: usize,
}
impl<A: Iterator, B: Iterator> Zip<A, B> {
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
b,
index: 0, // unused
len: 0, // unused
+ a_len: 0, // unused
}
}
B: TrustedRandomAccess + Iterator,
{
fn new(a: A, b: B) -> Self {
- let len = cmp::min(a.size(), b.size());
- Zip { a, b, index: 0, len }
+ let a_len = a.size();
+ let len = cmp::min(a_len, b.size());
+ Zip { a, b, index: 0, len, a_len }
}
#[inline]
unsafe {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
- } else if A::may_have_side_effect() && self.index < self.a.size() {
+ } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
+ let i = self.index;
+ self.index += 1;
+ self.len += 1;
// match the base implementation's potential side effects
- // SAFETY: we just checked that `self.index` < `self.a.len()`
+ // SAFETY: we just checked that `i` < `self.a.len()`
unsafe {
- self.a.__iterator_get_unchecked(self.index);
+ self.a.__iterator_get_unchecked(i);
}
- self.index += 1;
None
} else {
None
while self.index < end {
let i = self.index;
self.index += 1;
- if A::may_have_side_effect() {
+ if A::MAY_HAVE_SIDE_EFFECT {
// SAFETY: the usage of `cmp::min` to calculate `delta`
// ensures that `end` is smaller than or equal to `self.len`,
// so `i` is also smaller than `self.len`.
self.a.__iterator_get_unchecked(i);
}
}
- if B::may_have_side_effect() {
+ if B::MAY_HAVE_SIDE_EFFECT {
// SAFETY: same as above.
unsafe {
self.b.__iterator_get_unchecked(i);
A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator,
{
- let a_side_effect = A::may_have_side_effect();
- let b_side_effect = B::may_have_side_effect();
- if a_side_effect || b_side_effect {
+ if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
let sz_a = self.a.size();
let sz_b = self.b.size();
// Adjust a, b to equal length, make sure that only the first call
// on calls to `self.next_back()` after calling `get_unchecked()`.
if sz_a != sz_b {
let sz_a = self.a.size();
- if a_side_effect && sz_a > self.len {
- for _ in 0..sz_a - cmp::max(self.len, self.index) {
+ if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
+ for _ in 0..sz_a - self.len {
self.a.next_back();
}
+ self.a_len = self.len;
}
let sz_b = self.b.size();
- if b_side_effect && sz_b > self.len {
+ if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
for _ in 0..sz_b - self.len {
self.b.next_back();
}
}
if self.index < self.len {
self.len -= 1;
+ self.a_len -= 1;
let i = self.len;
// SAFETY: `i` is smaller than the previous value of `self.len`,
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
A: TrustedRandomAccess,
B: TrustedRandomAccess,
{
- fn may_have_side_effect() -> bool {
- A::may_have_side_effect() || B::may_have_side_effect()
- }
+ const MAY_HAVE_SIDE_EFFECT: bool = A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT;
}
#[stable(feature = "fused", since = "1.26.0")]
{
self.size_hint().0
}
- /// Returns `true` if getting an iterator element may have
- /// side effects. Remember to take inner iterators into account.
- fn may_have_side_effect() -> bool;
+ /// `true` if getting an iterator element may have side effects.
+ /// Remember to take inner iterators into account.
+ const MAY_HAVE_SIDE_EFFECT: bool;
}
/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to