Skip to content

Commit 2ad8c2f

Browse files
Rollup merge of #79173 - DeveloperC286:zip_nth_cleanup, r=kennytm
refactor: removing custom nth Zip fn Noticed `super_nth()` that seems very similar to `nth()` in `iterator.rs`. If you look at `nth()` in `iterator.rs` before the commit `ecacc7534b6bf50205c37c89402565b82d95a257` `super_nth()` looks exactly the same as `fn nth()` in `iterator.rs`. I may be misunderstanding something, but I think `super_nth()` can just be removed.
2 parents 7ce1b3b + 152f500 commit 2ad8c2f

File tree

1 file changed

+95
-134
lines changed
  • library/core/src/iter/adapters

1 file changed

+95
-134
lines changed

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

Lines changed: 95 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -17,93 +17,33 @@ pub struct Zip<A, B> {
1717
index: usize,
1818
len: usize,
1919
}
20-
impl<A: Iterator, B: Iterator> Zip<A, B> {
21-
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
22-
ZipImpl::new(a, b)
23-
}
24-
fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
25-
while let Some(x) = Iterator::next(self) {
26-
if n == 0 {
27-
return Some(x);
28-
}
29-
n -= 1;
30-
}
31-
None
32-
}
33-
}
3420

35-
#[stable(feature = "rust1", since = "1.0.0")]
36-
impl<A, B> Iterator for Zip<A, B>
21+
impl<A, B> Zip<A, B>
3722
where
3823
A: Iterator,
3924
B: Iterator,
4025
{
41-
type Item = (A::Item, B::Item);
42-
43-
#[inline]
44-
fn next(&mut self) -> Option<Self::Item> {
45-
ZipImpl::next(self)
46-
}
47-
48-
#[inline]
49-
fn size_hint(&self) -> (usize, Option<usize>) {
50-
ZipImpl::size_hint(self)
51-
}
52-
53-
#[inline]
54-
fn nth(&mut self, n: usize) -> Option<Self::Item> {
55-
ZipImpl::nth(self, n)
56-
}
57-
58-
#[inline]
59-
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
60-
where
61-
Self: TrustedRandomAccess,
62-
{
63-
// SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
64-
// requirements as `Iterator::__iterator_get_unchecked`.
65-
unsafe { ZipImpl::get_unchecked(self, idx) }
26+
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
27+
ZipNew::new(a, b)
6628
}
67-
}
6829

69-
#[stable(feature = "rust1", since = "1.0.0")]
70-
impl<A, B> DoubleEndedIterator for Zip<A, B>
71-
where
72-
A: DoubleEndedIterator + ExactSizeIterator,
73-
B: DoubleEndedIterator + ExactSizeIterator,
74-
{
75-
#[inline]
76-
fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
77-
ZipImpl::next_back(self)
30+
fn super_nth(&mut self, n: usize) -> Option<(A::Item, B::Item)> {
31+
self.advance_by(n).ok()?;
32+
self.next()
7833
}
7934
}
8035

81-
// Zip specialization trait
8236
#[doc(hidden)]
83-
trait ZipImpl<A, B> {
84-
type Item;
37+
trait ZipNew<A, B> {
8538
fn new(a: A, b: B) -> Self;
86-
fn next(&mut self) -> Option<Self::Item>;
87-
fn size_hint(&self) -> (usize, Option<usize>);
88-
fn nth(&mut self, n: usize) -> Option<Self::Item>;
89-
fn next_back(&mut self) -> Option<Self::Item>
90-
where
91-
A: DoubleEndedIterator + ExactSizeIterator,
92-
B: DoubleEndedIterator + ExactSizeIterator;
93-
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
94-
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
95-
where
96-
Self: Iterator + TrustedRandomAccess;
9739
}
9840

99-
// General Zip impl
10041
#[doc(hidden)]
101-
impl<A, B> ZipImpl<A, B> for Zip<A, B>
42+
impl<A, B> ZipNew<A, B> for Zip<A, B>
10243
where
10344
A: Iterator,
10445
B: Iterator,
10546
{
106-
type Item = (A::Item, B::Item);
10747
default fn new(a: A, b: B) -> Self {
10848
Zip {
10949
a,
@@ -112,25 +52,28 @@ where
11252
len: 0, // unused
11353
}
11454
}
55+
}
11556

116-
#[inline]
117-
default fn next(&mut self) -> Option<(A::Item, B::Item)> {
118-
let x = self.a.next()?;
119-
let y = self.b.next()?;
120-
Some((x, y))
121-
}
122-
123-
#[inline]
124-
default fn nth(&mut self, n: usize) -> Option<Self::Item> {
125-
self.super_nth(n)
57+
#[doc(hidden)]
58+
impl<A, B> ZipNew<A, B> for Zip<A, B>
59+
where
60+
A: TrustedRandomAccess + Iterator,
61+
B: TrustedRandomAccess + Iterator,
62+
{
63+
fn new(a: A, b: B) -> Self {
64+
let len = cmp::min(a.size(), b.size());
65+
Zip { a, b, index: 0, len }
12666
}
67+
}
12768

69+
#[stable(feature = "rust1", since = "1.0.0")]
70+
impl<A, B> DoubleEndedIterator for Zip<A, B>
71+
where
72+
A: DoubleEndedIterator + ExactSizeIterator,
73+
B: DoubleEndedIterator + ExactSizeIterator,
74+
{
12875
#[inline]
129-
default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
130-
where
131-
A: DoubleEndedIterator + ExactSizeIterator,
132-
B: DoubleEndedIterator + ExactSizeIterator,
133-
{
76+
default fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
13477
let a_sz = self.a.len();
13578
let b_sz = self.b.len();
13679
if a_sz != b_sz {
@@ -151,6 +94,71 @@ where
15194
_ => unreachable!(),
15295
}
15396
}
97+
}
98+
99+
#[stable(feature = "rust1", since = "1.0.0")]
100+
impl<A, B> DoubleEndedIterator for Zip<A, B>
101+
where
102+
A: TrustedRandomAccess + DoubleEndedIterator + ExactSizeIterator,
103+
B: TrustedRandomAccess + DoubleEndedIterator + ExactSizeIterator,
104+
{
105+
#[inline]
106+
fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
107+
let a_side_effect = A::may_have_side_effect();
108+
let b_side_effect = B::may_have_side_effect();
109+
if a_side_effect || b_side_effect {
110+
let sz_a = self.a.size();
111+
let sz_b = self.b.size();
112+
// Adjust a, b to equal length, make sure that only the first call
113+
// of `next_back` does this, otherwise we will break the restriction
114+
// on calls to `self.next_back()` after calling `get_unchecked()`.
115+
if sz_a != sz_b {
116+
if a_side_effect && sz_a > self.len {
117+
for _ in 0..sz_a - cmp::max(self.len, self.index) {
118+
self.a.next_back();
119+
}
120+
}
121+
122+
if b_side_effect && sz_b > self.len {
123+
for _ in 0..sz_b - self.len {
124+
self.b.next_back();
125+
}
126+
}
127+
}
128+
}
129+
if self.index < self.len {
130+
self.len -= 1;
131+
let i = self.len;
132+
// SAFETY: `i` is smaller than the previous value of `self.len`,
133+
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
134+
unsafe {
135+
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
136+
}
137+
} else {
138+
None
139+
}
140+
}
141+
}
142+
143+
#[stable(feature = "rust1", since = "1.0.0")]
144+
impl<A, B> Iterator for Zip<A, B>
145+
where
146+
A: Iterator,
147+
B: Iterator,
148+
{
149+
type Item = (A::Item, B::Item);
150+
151+
#[inline]
152+
default fn next(&mut self) -> Option<(A::Item, B::Item)> {
153+
let x = self.a.next()?;
154+
let y = self.b.next()?;
155+
Some((x, y))
156+
}
157+
158+
#[inline]
159+
default fn nth(&mut self, n: usize) -> Option<Self::Item> {
160+
self.super_nth(n)
161+
}
154162

155163
#[inline]
156164
default fn size_hint(&self) -> (usize, Option<usize>) {
@@ -169,25 +177,20 @@ where
169177
(lower, upper)
170178
}
171179

172-
default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item
180+
default unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item
173181
where
174182
Self: TrustedRandomAccess,
175183
{
176184
unreachable!("Always specialized");
177185
}
178186
}
179187

180-
#[doc(hidden)]
181-
impl<A, B> ZipImpl<A, B> for Zip<A, B>
188+
#[stable(feature = "rust1", since = "1.0.0")]
189+
impl<A, B> Iterator for Zip<A, B>
182190
where
183191
A: TrustedRandomAccess + Iterator,
184192
B: TrustedRandomAccess + Iterator,
185193
{
186-
fn new(a: A, b: B) -> Self {
187-
let len = cmp::min(a.size(), b.size());
188-
Zip { a, b, index: 0, len }
189-
}
190-
191194
#[inline]
192195
fn next(&mut self) -> Option<(A::Item, B::Item)> {
193196
if self.index < self.len {
@@ -243,49 +246,7 @@ where
243246
}
244247

245248
#[inline]
246-
fn next_back(&mut self) -> Option<(A::Item, B::Item)>
247-
where
248-
A: DoubleEndedIterator + ExactSizeIterator,
249-
B: DoubleEndedIterator + ExactSizeIterator,
250-
{
251-
let a_side_effect = A::may_have_side_effect();
252-
let b_side_effect = B::may_have_side_effect();
253-
if a_side_effect || b_side_effect {
254-
let sz_a = self.a.size();
255-
let sz_b = self.b.size();
256-
// Adjust a, b to equal length, make sure that only the first call
257-
// of `next_back` does this, otherwise we will break the restriction
258-
// on calls to `self.next_back()` after calling `get_unchecked()`.
259-
if sz_a != sz_b {
260-
let sz_a = self.a.size();
261-
if a_side_effect && sz_a > self.len {
262-
for _ in 0..sz_a - cmp::max(self.len, self.index) {
263-
self.a.next_back();
264-
}
265-
}
266-
let sz_b = self.b.size();
267-
if b_side_effect && sz_b > self.len {
268-
for _ in 0..sz_b - self.len {
269-
self.b.next_back();
270-
}
271-
}
272-
}
273-
}
274-
if self.index < self.len {
275-
self.len -= 1;
276-
let i = self.len;
277-
// SAFETY: `i` is smaller than the previous value of `self.len`,
278-
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
279-
unsafe {
280-
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
281-
}
282-
} else {
283-
None
284-
}
285-
}
286-
287-
#[inline]
288-
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
249+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
289250
let idx = self.index + idx;
290251
// SAFETY: the caller must uphold the contract for
291252
// `Iterator::__iterator_get_unchecked`.

0 commit comments

Comments
 (0)