5 DoubleEndedIterator, ExactSizeIterator, FusedIterator, InPlaceIterable, Iterator,
6 SourceIter, TrustedLen,
10 /// An iterator that iterates two other iterators simultaneously.
12 /// This `struct` is created by [`Iterator::zip`]. See its documentation
15 #[must_use = "iterators are lazy and do nothing unless consumed"]
16 #[stable(feature = "rust1", since = "1.0.0")]
17 pub struct Zip<A, B> {
20 // index and len are only used by the specialized version of zip
24 impl<A: Iterator, B: Iterator> Zip<A, B> {
25 pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
28 fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
29 while let Some(x) = Iterator::next(self) {
39 #[stable(feature = "rust1", since = "1.0.0")]
40 impl<A, B> Iterator for Zip<A, B>
45 type Item = (A::Item, B::Item);
48 fn next(&mut self) -> Option<Self::Item> {
53 fn size_hint(&self) -> (usize, Option<usize>) {
54 ZipImpl::size_hint(self)
58 fn nth(&mut self, n: usize) -> Option<Self::Item> {
63 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
65 Self: TrustedRandomAccess,
67 // SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
68 // requirements as `Iterator::__iterator_get_unchecked`.
69 unsafe { ZipImpl::get_unchecked(self, idx) }
73 #[stable(feature = "rust1", since = "1.0.0")]
74 impl<A, B> DoubleEndedIterator for Zip<A, B>
76 A: DoubleEndedIterator + ExactSizeIterator,
77 B: DoubleEndedIterator + ExactSizeIterator,
80 fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
81 ZipImpl::next_back(self)
85 // Zip specialization trait
89 fn new(a: A, b: B) -> Self;
90 fn next(&mut self) -> Option<Self::Item>;
91 fn size_hint(&self) -> (usize, Option<usize>);
92 fn nth(&mut self, n: usize) -> Option<Self::Item>;
93 fn next_back(&mut self) -> Option<Self::Item>
95 A: DoubleEndedIterator + ExactSizeIterator,
96 B: DoubleEndedIterator + ExactSizeIterator;
97 // This has the same safety requirements as `Iterator::__iterator_get_unchecked`
98 unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
100 Self: Iterator + TrustedRandomAccess;
105 impl<A, B> ZipImpl<A, B> for Zip<A, B>
110 type Item = (A::Item, B::Item);
111 default fn new(a: A, b: B) -> Self {
121 default fn next(&mut self) -> Option<(A::Item, B::Item)> {
122 let x = self.a.next()?;
123 let y = self.b.next()?;
128 default fn nth(&mut self, n: usize) -> Option<Self::Item> {
133 default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
135 A: DoubleEndedIterator + ExactSizeIterator,
136 B: DoubleEndedIterator + ExactSizeIterator,
138 let a_sz = self.a.len();
139 let b_sz = self.b.len();
141 // Adjust a, b to equal length
143 for _ in 0..a_sz - b_sz {
147 for _ in 0..b_sz - a_sz {
152 match (self.a.next_back(), self.b.next_back()) {
153 (Some(x), Some(y)) => Some((x, y)),
154 (None, None) => None,
160 default fn size_hint(&self) -> (usize, Option<usize>) {
161 let (a_lower, a_upper) = self.a.size_hint();
162 let (b_lower, b_upper) = self.b.size_hint();
164 let lower = cmp::min(a_lower, b_lower);
166 let upper = match (a_upper, b_upper) {
167 (Some(x), Some(y)) => Some(cmp::min(x, y)),
168 (Some(x), None) => Some(x),
169 (None, Some(y)) => Some(y),
170 (None, None) => None,
176 default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item
178 Self: TrustedRandomAccess,
180 unreachable!("Always specialized");
185 impl<A, B> ZipImpl<A, B> for Zip<A, B>
187 A: TrustedRandomAccess + Iterator,
188 B: TrustedRandomAccess + Iterator,
190 fn new(a: A, b: B) -> Self {
191 let len = cmp::min(a.size(), b.size());
192 Zip { a, b, index: 0, len }
196 fn next(&mut self) -> Option<(A::Item, B::Item)> {
197 if self.index < self.len {
200 // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
202 Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
204 } else if A::may_have_side_effect() && self.index < self.a.size() {
205 // match the base implementation's potential side effects
206 // SAFETY: we just checked that `self.index` < `self.a.len()`
208 self.a.__iterator_get_unchecked(self.index);
218 fn size_hint(&self) -> (usize, Option<usize>) {
219 let len = self.len - self.index;
224 fn nth(&mut self, n: usize) -> Option<Self::Item> {
225 let delta = cmp::min(n, self.len - self.index);
226 let end = self.index + delta;
227 while self.index < end {
230 if A::may_have_side_effect() {
231 // SAFETY: the usage of `cmp::min` to calculate `delta`
232 // ensures that `end` is smaller than or equal to `self.len`,
233 // so `i` is also smaller than `self.len`.
235 self.a.__iterator_get_unchecked(i);
238 if B::may_have_side_effect() {
239 // SAFETY: same as above.
241 self.b.__iterator_get_unchecked(i);
246 self.super_nth(n - delta)
250 fn next_back(&mut self) -> Option<(A::Item, B::Item)>
252 A: DoubleEndedIterator + ExactSizeIterator,
253 B: DoubleEndedIterator + ExactSizeIterator,
255 let a_side_effect = A::may_have_side_effect();
256 let b_side_effect = B::may_have_side_effect();
257 if a_side_effect || b_side_effect {
258 let sz_a = self.a.size();
259 let sz_b = self.b.size();
260 // Adjust a, b to equal length, make sure that only the first call
261 // of `next_back` does this, otherwise we will break the restriction
262 // on calls to `self.next_back()` after calling `get_unchecked()`.
264 let sz_a = self.a.size();
265 if a_side_effect && sz_a > self.len {
266 for _ in 0..sz_a - cmp::max(self.len, self.index) {
270 let sz_b = self.b.size();
271 if b_side_effect && sz_b > self.len {
272 for _ in 0..sz_b - self.len {
278 if self.index < self.len {
281 // SAFETY: `i` is smaller than the previous value of `self.len`,
282 // which is also smaller than or equal to `self.a.len()` and `self.b.len()`
284 Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
292 unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
293 // SAFETY: the caller must uphold the contract for
294 // `Iterator::__iterator_get_unchecked`.
295 unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
299 #[stable(feature = "rust1", since = "1.0.0")]
300 impl<A, B> ExactSizeIterator for Zip<A, B>
302 A: ExactSizeIterator,
303 B: ExactSizeIterator,
308 #[unstable(feature = "trusted_random_access", issue = "none")]
309 unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
311 A: TrustedRandomAccess,
312 B: TrustedRandomAccess,
314 fn may_have_side_effect() -> bool {
315 A::may_have_side_effect() || B::may_have_side_effect()
319 #[stable(feature = "fused", since = "1.26.0")]
320 impl<A, B> FusedIterator for Zip<A, B>
327 #[unstable(feature = "trusted_len", issue = "37572")]
328 unsafe impl<A, B> TrustedLen for Zip<A, B>
335 // Arbitrarily selects the left side of the zip iteration as extractable "source"
336 // it would require negative trait bounds to be able to try both
337 #[unstable(issue = "none", feature = "inplace_iteration")]
338 unsafe impl<S, A, B> SourceIter for Zip<A, B>
340 A: SourceIter<Source = S>,
347 unsafe fn as_inner(&mut self) -> &mut S {
348 // SAFETY: unsafe function forwarding to unsafe function with the same requirements
349 unsafe { SourceIter::as_inner(&mut self.a) }
353 #[unstable(issue = "none", feature = "inplace_iteration")]
354 // Limited to Item: Copy since interaction between Zip's use of TrustedRandomAccess
355 // and Drop implementation of the source is unclear.
357 // An additional method returning the number of times the source has been logically advanced
358 // (without calling next()) would be needed to properly drop the remainder of the source.
359 unsafe impl<A: InPlaceIterable, B: Iterator> InPlaceIterable for Zip<A, B> where A::Item: Copy {}
361 #[stable(feature = "rust1", since = "1.0.0")]
362 impl<A: Debug, B: Debug> Debug for Zip<A, B> {
363 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
372 impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
373 default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374 f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish()
378 impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B> for Zip<A, B> {
379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380 // It's *not safe* to call fmt on the contained iterators, since once
381 // we start iterating they're in strange, potentially unsafe, states.
382 f.debug_struct("Zip").finish()
386 /// An iterator whose items are random-accessible efficiently
390 /// The iterator's `size_hint` must be exact and cheap to call.
392 /// `size` may not be overridden.
394 /// `<Self as Iterator>::__iterator_get_unchecked` must be safe to call
395 /// provided the following conditions are met.
397 /// 1. `0 <= idx` and `idx < self.size()`.
398 /// 2. If `self: !Clone`, then `get_unchecked` is never called with the same
399 /// index on `self` more than once.
400 /// 3. After `self.get_unchecked(idx)` has been called then `next_back` will
401 /// only be called at most `self.size() - idx - 1` times.
402 /// 4. After `get_unchecked` is called, then only the following methods will be
403 /// called on `self`:
404 /// * `std::clone::Clone::clone`
405 /// * `std::iter::Iterator::size_hint()`
406 /// * `std::iter::Iterator::next_back()`
407 /// * `std::iter::Iterator::__iterator_get_unchecked()`
408 /// * `std::iter::TrustedRandomAccess::size()`
410 /// Further, given that these conditions are met, it must guarantee that:
412 /// * It does not change the value returned from `size_hint`
413 /// * It must be safe to call the methods listed above on `self` after calling
414 /// `get_unchecked`, assuming that the required traits are implemented.
415 /// * It must also be safe to drop `self` after calling `get_unchecked`.
417 #[unstable(feature = "trusted_random_access", issue = "none")]
418 #[rustc_specialization_trait]
419 pub unsafe trait TrustedRandomAccess: Sized {
420 // Convenience method.
421 fn size(&self) -> usize
427 /// Returns `true` if getting an iterator element may have
428 /// side effects. Remember to take inner iterators into account.
429 fn may_have_side_effect() -> bool;
432 /// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to
433 /// know that `U: TrustedRandomAccess`.
437 /// Same requirements calling `get_unchecked` directly.
439 pub(in crate::iter::adapters) unsafe fn try_get_unchecked<I>(it: &mut I, idx: usize) -> I::Item
443 // SAFETY: the caller must uphold the contract for
444 // `Iterator::__iterator_get_unchecked`.
445 unsafe { it.try_get_unchecked(idx) }
448 unsafe trait SpecTrustedRandomAccess: Iterator {
449 /// If `Self: TrustedRandomAccess`, it must be safe to call a
450 /// `Iterator::__iterator_get_unchecked(self, index)`.
451 unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
454 unsafe impl<I: Iterator> SpecTrustedRandomAccess for I {
455 default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item {
456 panic!("Should only be called on TrustedRandomAccess iterators");
460 unsafe impl<I: Iterator + TrustedRandomAccess> SpecTrustedRandomAccess for I {
461 unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
462 // SAFETY: the caller must uphold the contract for
463 // `Iterator::__iterator_get_unchecked`.
464 unsafe { self.__iterator_get_unchecked(index) }