Rollup merge of #82292 - SkiFire13:fix-issue-82291, r=m-ou-se
Prevent specialized ZipImpl from calling `__iterator_get_unchecked` twice with the same index Fixes #82291 It's open for review, but conflicts with #82289, wait before merging. The conflict involves only the new test, so it should be rather trivial to fix.
This commit is contained in:
commit
1d5b2dc945
|
@ -13,9 +13,10 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
|
|||
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> {
|
||||
|
@ -110,6 +111,7 @@ where
|
|||
b,
|
||||
index: 0, // unused
|
||||
len: 0, // unused
|
||||
a_len: 0, // unused
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,8 +186,9 @@ where
|
|||
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]
|
||||
|
@ -197,7 +200,7 @@ where
|
|||
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;
|
||||
|
@ -262,6 +265,7 @@ where
|
|||
for _ in 0..sz_a - self.len {
|
||||
self.a.next_back();
|
||||
}
|
||||
self.a_len = self.len;
|
||||
}
|
||||
let sz_b = self.b.size();
|
||||
if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
|
||||
|
@ -273,6 +277,7 @@ where
|
|||
}
|
||||
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()`
|
||||
|
|
|
@ -265,3 +265,26 @@ fn test_issue_82282() {
|
|||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_issue_82291() {
|
||||
use std::cell::Cell;
|
||||
|
||||
let mut v1 = [()];
|
||||
let v2 = [()];
|
||||
|
||||
let called = Cell::new(0);
|
||||
|
||||
let mut zip = v1
|
||||
.iter_mut()
|
||||
.map(|r| {
|
||||
called.set(called.get() + 1);
|
||||
r
|
||||
})
|
||||
.zip(&v2);
|
||||
|
||||
zip.next_back();
|
||||
assert_eq!(called.get(), 1);
|
||||
zip.next();
|
||||
assert_eq!(called.get(), 1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue