diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 2f8f504d8fcaa..c720ed7daa53e 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -18,18 +18,19 @@ pub struct Zip { len: usize, a_len: usize, } -impl Zip { + +impl Zip +where + A: Iterator, + B: Iterator, +{ pub(in crate::iter) fn new(a: A, b: B) -> Zip { - ZipImpl::new(a, b) + ZipNew::new(a, b) } - fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> { - while let Some(x) = Iterator::next(self) { - if n == 0 { - return Some(x); - } - n -= 1; - } - None + + fn super_nth(&mut self, n: usize) -> Option<(A::Item, B::Item)> { + self.advance_by(n).ok()?; + self.next() } } @@ -61,81 +62,20 @@ where A: IntoIterator, B: IntoIterator, { - ZipImpl::new(a.into_iter(), b.into_iter()) + ZipNew::new(a.into_iter(), b.into_iter()) } -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Zip -where - A: Iterator, - B: Iterator, -{ - type Item = (A::Item, B::Item); - - #[inline] - fn next(&mut self) -> Option { - ZipImpl::next(self) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - ZipImpl::size_hint(self) - } - - #[inline] - fn nth(&mut self, n: usize) -> Option { - ZipImpl::nth(self, n) - } - - #[inline] - unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item - where - Self: TrustedRandomAccess, - { - // SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety - // requirements as `Iterator::__iterator_get_unchecked`. - unsafe { ZipImpl::get_unchecked(self, idx) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Zip -where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator, -{ - #[inline] - fn next_back(&mut self) -> Option<(A::Item, B::Item)> { - ZipImpl::next_back(self) - } -} - -// Zip specialization trait #[doc(hidden)] -trait ZipImpl { - type Item; +trait ZipNew { fn new(a: A, b: B) -> Self; - fn next(&mut self) -> Option; - fn size_hint(&self) -> (usize, Option); - fn nth(&mut self, n: usize) -> Option; - fn next_back(&mut self) -> Option - where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator; - // This has the same safety requirements as `Iterator::__iterator_get_unchecked` - unsafe fn get_unchecked(&mut self, idx: usize) -> ::Item - where - Self: Iterator + TrustedRandomAccess; } -// General Zip impl #[doc(hidden)] -impl ZipImpl for Zip +impl ZipNew for Zip where A: Iterator, B: Iterator, { - type Item = (A::Item, B::Item); default fn new(a: A, b: B) -> Self { Zip { a, @@ -145,25 +85,29 @@ where a_len: 0, // unused } } +} - #[inline] - default fn next(&mut self) -> Option<(A::Item, B::Item)> { - let x = self.a.next()?; - let y = self.b.next()?; - Some((x, y)) - } - - #[inline] - default fn nth(&mut self, n: usize) -> Option { - self.super_nth(n) +#[doc(hidden)] +impl ZipNew for Zip +where + A: TrustedRandomAccess + Iterator, + B: TrustedRandomAccess + Iterator, +{ + fn new(a: A, b: B) -> Self { + let a_len = a.size(); + let len = cmp::min(a_len, b.size()); + Zip { a, b, index: 0, len, a_len } } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Zip +where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, +{ #[inline] - default fn next_back(&mut self) -> Option<(A::Item, B::Item)> - where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator, - { + default fn next_back(&mut self) -> Option<(A::Item, B::Item)> { let a_sz = self.a.len(); let b_sz = self.b.len(); if a_sz != b_sz { @@ -184,6 +128,75 @@ where _ => unreachable!(), } } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Zip +where + A: TrustedRandomAccess + DoubleEndedIterator + ExactSizeIterator, + B: TrustedRandomAccess + DoubleEndedIterator + ExactSizeIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<(A::Item, B::Item)> + where + A: DoubleEndedIterator + ExactSizeIterator, + B: DoubleEndedIterator + ExactSizeIterator, + { + 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 + // of `next_back` does this, otherwise we will break the restriction + // on calls to `self.next_back()` after calling `get_unchecked()`. + if sz_a != sz_b { + 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; + } + + 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()` + unsafe { + Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) + } + } else { + None + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Zip +where + A: Iterator, + B: Iterator, +{ + type Item = (A::Item, B::Item); + + #[inline] + default fn next(&mut self) -> Option<(A::Item, B::Item)> { + let x = self.a.next()?; + let y = self.b.next()?; + Some((x, y)) + } + + #[inline] + default fn nth(&mut self, n: usize) -> Option { + self.super_nth(n) + } #[inline] default fn size_hint(&self) -> (usize, Option) { @@ -202,7 +215,7 @@ where (lower, upper) } - default unsafe fn get_unchecked(&mut self, _idx: usize) -> ::Item + default unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> ::Item where Self: TrustedRandomAccess, { @@ -210,18 +223,12 @@ where } } -#[doc(hidden)] -impl ZipImpl for Zip +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Zip where A: TrustedRandomAccess + Iterator, B: TrustedRandomAccess + Iterator, { - fn new(a: A, b: B) -> Self { - let a_len = a.size(); - let len = cmp::min(a_len, b.size()); - Zip { a, b, index: 0, len, a_len } - } - #[inline] fn next(&mut self) -> Option<(A::Item, B::Item)> { if self.index < self.len { @@ -279,49 +286,7 @@ where } #[inline] - fn next_back(&mut self) -> Option<(A::Item, B::Item)> - where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator, - { - 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 - // of `next_back` does this, otherwise we will break the restriction - // on calls to `self.next_back()` after calling `get_unchecked()`. - if sz_a != sz_b { - let sz_a = self.a.size(); - 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::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()` - unsafe { - Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) - } - } else { - None - } - } - - #[inline] - unsafe fn get_unchecked(&mut self, idx: usize) -> ::Item { + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> ::Item { let idx = self.index + idx; // SAFETY: the caller must uphold the contract for // `Iterator::__iterator_get_unchecked`.