Skip to content

Commit bfb0e4a

Browse files
committed
refactor: moved next_back out of ZipImpl
1 parent 8db2782 commit bfb0e4a

File tree

1 file changed

+64
-74
lines changed
  • library/core/src/iter/adapters

1 file changed

+64
-74
lines changed

library/core/src/iter/adapters/zip.rs

Lines changed: 64 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,73 @@ impl<A, B> DoubleEndedIterator for Zip<A, B>
105105
where
106106
A: DoubleEndedIterator + ExactSizeIterator,
107107
B: DoubleEndedIterator + ExactSizeIterator,
108+
{
109+
#[inline]
110+
default fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
111+
let a_sz = self.a.len();
112+
let b_sz = self.b.len();
113+
if a_sz != b_sz {
114+
// Adjust a, b to equal length
115+
if a_sz > b_sz {
116+
for _ in 0..a_sz - b_sz {
117+
self.a.next_back();
118+
}
119+
} else {
120+
for _ in 0..b_sz - a_sz {
121+
self.b.next_back();
122+
}
123+
}
124+
}
125+
match (self.a.next_back(), self.b.next_back()) {
126+
(Some(x), Some(y)) => Some((x, y)),
127+
(None, None) => None,
128+
_ => unreachable!(),
129+
}
130+
}
131+
}
132+
133+
#[stable(feature = "rust1", since = "1.0.0")]
134+
impl<A, B> DoubleEndedIterator for Zip<A, B>
135+
where
136+
A: TrustedRandomAccess + DoubleEndedIterator + ExactSizeIterator,
137+
B: TrustedRandomAccess + DoubleEndedIterator + ExactSizeIterator,
108138
{
109139
#[inline]
110140
fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
111-
ZipImpl::next_back(self)
141+
let a_side_effect = A::may_have_side_effect();
142+
let b_side_effect = B::may_have_side_effect();
143+
if a_side_effect || b_side_effect {
144+
let sz_a = self.a.size();
145+
let sz_b = self.b.size();
146+
// Adjust a, b to equal length, make sure that only the first call
147+
// of `next_back` does this, otherwise we will break the restriction
148+
// on calls to `self.next_back()` after calling `get_unchecked()`.
149+
if sz_a != sz_b {
150+
let sz_a = self.a.size();
151+
if a_side_effect && sz_a > self.len {
152+
for _ in 0..sz_a - cmp::max(self.len, self.index) {
153+
self.a.next_back();
154+
}
155+
}
156+
let sz_b = self.b.size();
157+
if b_side_effect && sz_b > self.len {
158+
for _ in 0..sz_b - self.len {
159+
self.b.next_back();
160+
}
161+
}
162+
}
163+
}
164+
if self.index < self.len {
165+
self.len -= 1;
166+
let i = self.len;
167+
// SAFETY: `i` is smaller than the previous value of `self.len`,
168+
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
169+
unsafe {
170+
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
171+
}
172+
} else {
173+
None
174+
}
112175
}
113176
}
114177

@@ -119,10 +182,6 @@ trait ZipImpl<A, B> {
119182
fn next(&mut self) -> Option<Self::Item>;
120183
fn size_hint(&self) -> (usize, Option<usize>);
121184
fn nth(&mut self, n: usize) -> Option<Self::Item>;
122-
fn next_back(&mut self) -> Option<Self::Item>
123-
where
124-
A: DoubleEndedIterator + ExactSizeIterator,
125-
B: DoubleEndedIterator + ExactSizeIterator;
126185
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
127186
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
128187
where
@@ -150,33 +209,6 @@ where
150209
self.super_nth(n)
151210
}
152211

153-
#[inline]
154-
default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
155-
where
156-
A: DoubleEndedIterator + ExactSizeIterator,
157-
B: DoubleEndedIterator + ExactSizeIterator,
158-
{
159-
let a_sz = self.a.len();
160-
let b_sz = self.b.len();
161-
if a_sz != b_sz {
162-
// Adjust a, b to equal length
163-
if a_sz > b_sz {
164-
for _ in 0..a_sz - b_sz {
165-
self.a.next_back();
166-
}
167-
} else {
168-
for _ in 0..b_sz - a_sz {
169-
self.b.next_back();
170-
}
171-
}
172-
}
173-
match (self.a.next_back(), self.b.next_back()) {
174-
(Some(x), Some(y)) => Some((x, y)),
175-
(None, None) => None,
176-
_ => unreachable!(),
177-
}
178-
}
179-
180212
#[inline]
181213
default fn size_hint(&self) -> (usize, Option<usize>) {
182214
let (a_lower, a_upper) = self.a.size_hint();
@@ -262,48 +294,6 @@ where
262294
self.super_nth(n - delta)
263295
}
264296

265-
#[inline]
266-
fn next_back(&mut self) -> Option<(A::Item, B::Item)>
267-
where
268-
A: DoubleEndedIterator + ExactSizeIterator,
269-
B: DoubleEndedIterator + ExactSizeIterator,
270-
{
271-
let a_side_effect = A::may_have_side_effect();
272-
let b_side_effect = B::may_have_side_effect();
273-
if a_side_effect || b_side_effect {
274-
let sz_a = self.a.size();
275-
let sz_b = self.b.size();
276-
// Adjust a, b to equal length, make sure that only the first call
277-
// of `next_back` does this, otherwise we will break the restriction
278-
// on calls to `self.next_back()` after calling `get_unchecked()`.
279-
if sz_a != sz_b {
280-
let sz_a = self.a.size();
281-
if a_side_effect && sz_a > self.len {
282-
for _ in 0..sz_a - cmp::max(self.len, self.index) {
283-
self.a.next_back();
284-
}
285-
}
286-
let sz_b = self.b.size();
287-
if b_side_effect && sz_b > self.len {
288-
for _ in 0..sz_b - self.len {
289-
self.b.next_back();
290-
}
291-
}
292-
}
293-
}
294-
if self.index < self.len {
295-
self.len -= 1;
296-
let i = self.len;
297-
// SAFETY: `i` is smaller than the previous value of `self.len`,
298-
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
299-
unsafe {
300-
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
301-
}
302-
} else {
303-
None
304-
}
305-
}
306-
307297
#[inline]
308298
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
309299
let idx = self.index + idx;

0 commit comments

Comments
 (0)