1use crate::cmp;
2use crate::fmt::{self, Debug};
3use crate::iter::{
4FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, UncheckedIterator,
5};
6use crate::num::NonZero;
78/// An iterator that iterates two other iterators simultaneously.
9///
10/// This `struct` is created by [`zip`] or [`Iterator::zip`].
11/// See their documentation for more.
12#[derive(#[automatically_derived]
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: crate::clone::Clone, B: crate::clone::Clone> crate::clone::Clone for
Zip<A, B> {
#[inline]
fn clone(&self) -> Zip<A, B> {
Zip {
a: crate::clone::Clone::clone(&self.a),
b: crate::clone::Clone::clone(&self.b),
index: crate::clone::Clone::clone(&self.index),
len: crate::clone::Clone::clone(&self.len),
}
}
}Clone)]
13#[must_use = "iterators are lazy and do nothing unless consumed"]
14#[stable(feature = "rust1", since = "1.0.0")]
15pub struct Zip<A, B> {
16 a: A,
17 b: B,
18// index, len and a_len are only used by the specialized version of zip
19index: usize,
20 len: usize,
21}
22impl<A: Iterator, B: Iterator> Zip<A, B> {
23pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
24 ZipImpl::new(a, b)
25 }
26fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
27while let Some(x) = Iterator::next(self) {
28if n == 0 {
29return Some(x);
30 }
31 n -= 1;
32 }
33None34 }
35}
3637/// Converts the arguments to iterators and zips them.
38///
39/// See the documentation of [`Iterator::zip`] for more.
40///
41/// # Examples
42///
43/// ```
44/// use std::iter::zip;
45///
46/// let xs = [1, 2, 3];
47/// let ys = [4, 5, 6];
48///
49/// let mut iter = zip(xs, ys);
50///
51/// assert_eq!(iter.next().unwrap(), (1, 4));
52/// assert_eq!(iter.next().unwrap(), (2, 5));
53/// assert_eq!(iter.next().unwrap(), (3, 6));
54/// assert!(iter.next().is_none());
55///
56/// // Nested zips are also possible:
57/// let zs = [7, 8, 9];
58///
59/// let mut iter = zip(zip(xs, ys), zs);
60///
61/// assert_eq!(iter.next().unwrap(), ((1, 4), 7));
62/// assert_eq!(iter.next().unwrap(), ((2, 5), 8));
63/// assert_eq!(iter.next().unwrap(), ((3, 6), 9));
64/// assert!(iter.next().is_none());
65/// ```
66#[stable(feature = "iter_zip", since = "1.59.0")]
67pub fn zip<A, B>(a: A, b: B) -> Zip<A::IntoIter, B::IntoIter>
68where
69A: IntoIterator,
70 B: IntoIterator,
71{
72 ZipImpl::new(a.into_iter(), b.into_iter())
73}
7475#[stable(feature = "rust1", since = "1.0.0")]
76impl<A, B> Iteratorfor Zip<A, B>
77where
78A: Iterator,
79 B: Iterator,
80{
81type Item = (A::Item, B::Item);
8283#[inline]
84fn next(&mut self) -> Option<Self::Item> {
85 ZipImpl::next(self)
86 }
8788#[inline]
89fn size_hint(&self) -> (usize, Option<usize>) {
90 ZipImpl::size_hint(self)
91 }
9293#[inline]
94fn nth(&mut self, n: usize) -> Option<Self::Item> {
95 ZipImpl::nth(self, n)
96 }
9798#[inline]
99fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
100where
101F: FnMut(Acc, Self::Item) -> Acc,
102 {
103 ZipImpl::fold(self, init, f)
104 }
105106#[inline]
107unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
108where
109Self: TrustedRandomAccessNoCoerce,
110 {
111// SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
112 // requirements as `Iterator::__iterator_get_unchecked`.
113unsafe { ZipImpl::get_unchecked(self, idx) }
114 }
115}
116117#[stable(feature = "rust1", since = "1.0.0")]
118impl<A, B> DoubleEndedIteratorfor Zip<A, B>
119where
120A: DoubleEndedIterator + ExactSizeIterator,
121 B: DoubleEndedIterator + ExactSizeIterator,
122{
123#[inline]
124fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
125 ZipImpl::next_back(self)
126 }
127}
128129// Zip specialization trait
130#[doc(hidden)]
131trait ZipImpl<A, B> {
132type Item;
133fn new(a: A, b: B) -> Self;
134fn next(&mut self) -> Option<Self::Item>;
135fn size_hint(&self) -> (usize, Option<usize>);
136fn nth(&mut self, n: usize) -> Option<Self::Item>;
137fn next_back(&mut self) -> Option<Self::Item>
138where
139A: DoubleEndedIterator + ExactSizeIterator,
140 B: DoubleEndedIterator + ExactSizeIterator;
141fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
142where
143F: FnMut(Acc, Self::Item) -> Acc;
144// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
145unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item146where
147Self: Iterator + TrustedRandomAccessNoCoerce;
148}
149150// Work around limitations of specialization, requiring `default` impls to be repeated
151// in intermediary impls.
152macro_rules!zip_impl_general_defaults {
153 () => {
154 default fn new(a: A, b: B) -> Self {
155 Zip {
156 a,
157 b,
158 index: 0, // unused
159len: 0, // unused
160}
161 }
162163#[inline]
164default fn next(&mut self) -> Option<(A::Item, B::Item)> {
165let x = self.a.next()?;
166let y = self.b.next()?;
167Some((x, y))
168 }
169170#[inline]
171default fn nth(&mut self, n: usize) -> Option<Self::Item> {
172self.super_nth(n)
173 }
174175#[inline]
176default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
177where
178A: DoubleEndedIterator + ExactSizeIterator,
179 B: DoubleEndedIterator + ExactSizeIterator,
180 {
181// The function body below only uses `self.a/b.len()` and `self.a/b.next_back()`
182 // and doesn’t call `next_back` too often, so this implementation is safe in
183 // the `TrustedRandomAccessNoCoerce` specialization
184185let a_sz = self.a.len();
186let b_sz = self.b.len();
187if a_sz != b_sz {
188// Adjust a, b to equal length
189if a_sz > b_sz {
190for _ in 0..a_sz - b_sz {
191self.a.next_back();
192 }
193 } else {
194for _ in 0..b_sz - a_sz {
195self.b.next_back();
196 }
197 }
198 }
199match (self.a.next_back(), self.b.next_back()) {
200 (Some(x), Some(y)) => Some((x, y)),
201 (None, None) => None,
202_ => unreachable!(),
203 }
204 }
205 };
206}
207208// General Zip impl
209#[doc(hidden)]
210impl<A, B> ZipImpl<A, B> for Zip<A, B>
211where
212A: Iterator,
213 B: Iterator,
214{
215type Item = (A::Item, B::Item);
216217A
a
B
b
Self
Zip { a, b, index: 0, len: 0 };
&mut Self
self
Option<(A::Item, B::Item)>
let x = self.a.next()?;
let y = self.b.next()?;
Some((x, y));
&mut Self
self
usize
n
Option<Self::Item>
self.super_nth(n);
A
B
&mut Self
self
Option<(A::Item, B::Item)>
let a_sz = self.a.len();
let b_sz = self.b.len();
if a_sz != b_sz {
if a_sz > b_sz {
for _ in 0..a_sz - b_sz { self.a.next_back(); }
} else { for _ in 0..b_sz - a_sz { self.b.next_back(); } }
}
match (self.a.next_back(), self.b.next_back()) {
(Some(x), Some(y)) => Some((x, y)),
(None, None) => None,
_ => crate::panicking::panic("internal error: entered unreachable code"),
}zip_impl_general_defaults! {}218219#[inline]
220default fn size_hint(&self) -> (usize, Option<usize>) {
221let (a_lower, a_upper) = self.a.size_hint();
222let (b_lower, b_upper) = self.b.size_hint();
223224let lower = cmp::min(a_lower, b_lower);
225226let upper = match (a_upper, b_upper) {
227 (Some(x), Some(y)) => Some(cmp::min(x, y)),
228 (Some(x), None) => Some(x),
229 (None, Some(y)) => Some(y),
230 (None, None) => None,
231 };
232233 (lower, upper)
234 }
235236 default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item237where
238Self: TrustedRandomAccessNoCoerce,
239 {
240{
crate::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Always specialized")));
};unreachable!("Always specialized");
241 }
242243#[inline]
244default fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
245where
246F: FnMut(Acc, Self::Item) -> Acc,
247 {
248 SpecFold::spec_fold(self, init, f)
249 }
250}
251252#[doc(hidden)]
253impl<A, B> ZipImpl<A, B> for Zip<A, B>
254where
255A: TrustedRandomAccessNoCoerce + Iterator,
256 B: TrustedRandomAccessNoCoerce + Iterator,
257{
258A
a
B
b
Self
Zip { a, b, index: 0, len: 0 };
&mut Self
self
Option<(A::Item, B::Item)>
let x = self.a.next()?;
let y = self.b.next()?;
Some((x, y));
&mut Self
self
usize
n
Option<Self::Item>
self.super_nth(n);
A
B
&mut Self
self
Option<(A::Item, B::Item)>
let a_sz = self.a.len();
let b_sz = self.b.len();
if a_sz != b_sz {
if a_sz > b_sz {
for _ in 0..a_sz - b_sz { self.a.next_back(); }
} else { for _ in 0..b_sz - a_sz { self.b.next_back(); } }
}
match (self.a.next_back(), self.b.next_back()) {
(Some(x), Some(y)) => Some((x, y)),
(None, None) => None,
_ => crate::panicking::panic("internal error: entered unreachable code"),
}zip_impl_general_defaults! {}259260#[inline]
261default fn size_hint(&self) -> (usize, Option<usize>) {
262let size = cmp::min(self.a.size(), self.b.size());
263 (size, Some(size))
264 }
265266#[inline]
267unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
268let idx = self.index + idx;
269// SAFETY: the caller must uphold the contract for
270 // `Iterator::__iterator_get_unchecked`.
271unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
272 }
273274#[inline]
275fn fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
276where
277F: FnMut(Acc, Self::Item) -> Acc,
278 {
279let mut accum = init;
280let len = ZipImpl::size_hint(&self).0;
281for i in 0..len {
282// SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to
283 // calculate the length and then use that to do unchecked iteration.
284 // fold consumes the iterator so we don't need to fixup any state.
285unsafe {
286 accum = f(accum, self.get_unchecked(i));
287 }
288 }
289accum290 }
291}
292293#[doc(hidden)]
294impl<A, B> ZipImpl<A, B> for Zip<A, B>
295where
296A: TrustedRandomAccess + Iterator,
297 B: TrustedRandomAccess + Iterator,
298{
299fn new(a: A, b: B) -> Self {
300let len = cmp::min(a.size(), b.size());
301Zip { a, b, index: 0, len }
302 }
303304#[inline]
305fn next(&mut self) -> Option<(A::Item, B::Item)> {
306if self.index < self.len {
307let i = self.index;
308// since get_unchecked executes code which can panic we increment the counters beforehand
309 // so that the same index won't be accessed twice, as required by TrustedRandomAccess
310self.index += 1;
311// SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
312unsafe {
313Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
314 }
315 } else {
316None317 }
318 }
319320#[inline]
321fn size_hint(&self) -> (usize, Option<usize>) {
322let len = self.len - self.index;
323 (len, Some(len))
324 }
325326#[inline]
327fn nth(&mut self, n: usize) -> Option<Self::Item> {
328let delta = cmp::min(n, self.len - self.index);
329let end = self.index + delta;
330while self.index < end {
331let i = self.index;
332// since get_unchecked executes code which can panic we increment the counters beforehand
333 // so that the same index won't be accessed twice, as required by TrustedRandomAccess
334self.index += 1;
335if A::MAY_HAVE_SIDE_EFFECT {
336// SAFETY: the usage of `cmp::min` to calculate `delta`
337 // ensures that `end` is smaller than or equal to `self.len`,
338 // so `i` is also smaller than `self.len`.
339unsafe {
340self.a.__iterator_get_unchecked(i);
341 }
342 }
343if B::MAY_HAVE_SIDE_EFFECT {
344// SAFETY: same as above.
345unsafe {
346self.b.__iterator_get_unchecked(i);
347 }
348 }
349 }
350351self.super_nth(n - delta)
352 }
353354#[inline]
355fn next_back(&mut self) -> Option<(A::Item, B::Item)>
356where
357A: DoubleEndedIterator + ExactSizeIterator,
358 B: DoubleEndedIterator + ExactSizeIterator,
359 {
360// No effects when the iterator is exhausted, to reduce the number of
361 // cases the unsafe code has to handle.
362 // See #137255 for a case where where too many epicycles lead to unsoundness.
363if self.index < self.len {
364let old_len = self.len;
365366// since get_unchecked and the side-effecting code can execute user code
367 // which can panic we decrement the counter beforehand
368 // so that the same index won't be accessed twice, as required by TrustedRandomAccess.
369 // Additionally this will ensure that the side-effects code won't run a second time.
370self.len -= 1;
371372// Adjust a, b to equal length if we're iterating backwards.
373if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
374// note if some forward-iteration already happened then these aren't the real
375 // remaining lengths of the inner iterators, so we have to relate them to
376 // Zip's internal length-tracking.
377let sz_a = self.a.size();
378let sz_b = self.b.size();
379// This condition can and must only be true on the first `next_back` call,
380 // otherwise we will break the restriction on calls to `self.next_back()`
381 // after calling `get_unchecked()`.
382if sz_a != sz_b && (old_len == sz_a || old_len == sz_b) {
383if A::MAY_HAVE_SIDE_EFFECT && sz_a > old_len {
384for _ in 0..sz_a - old_len {
385self.a.next_back();
386 }
387 }
388if B::MAY_HAVE_SIDE_EFFECT && sz_b > old_len {
389for _ in 0..sz_b - old_len {
390self.b.next_back();
391 }
392 }
393if true {
match (&self.a.size(), &self.b.size()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = crate::panicking::AssertKind::Eq;
crate::panicking::assert_failed(kind, &*left_val, &*right_val,
crate::option::Option::None);
}
}
};
};debug_assert_eq!(self.a.size(), self.b.size());
394 }
395 }
396let i = self.len;
397// SAFETY: `i` is smaller than the previous value of `self.len`,
398 // which is also smaller than or equal to `self.a.len()` and `self.b.len()`
399unsafe {
400Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
401 }
402 } else {
403None404 }
405 }
406}
407408#[stable(feature = "rust1", since = "1.0.0")]
409impl<A, B> ExactSizeIteratorfor Zip<A, B>
410where
411A: ExactSizeIterator,
412 B: ExactSizeIterator,
413{
414}
415416#[doc(hidden)]
417#[unstable(feature = "trusted_random_access", issue = "none")]
418unsafe impl<A, B> TrustedRandomAccessfor Zip<A, B>
419where
420A: TrustedRandomAccess,
421 B: TrustedRandomAccess,
422{
423}
424425#[doc(hidden)]
426#[unstable(feature = "trusted_random_access", issue = "none")]
427unsafe impl<A, B> TrustedRandomAccessNoCoercefor Zip<A, B>
428where
429A: TrustedRandomAccessNoCoerce,
430 B: TrustedRandomAccessNoCoerce,
431{
432const MAY_HAVE_SIDE_EFFECT: bool = A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT;
433}
434435#[stable(feature = "fused", since = "1.26.0")]
436impl<A, B> FusedIteratorfor Zip<A, B>
437where
438A: FusedIterator,
439 B: FusedIterator,
440{
441}
442443#[unstable(issue = "none", feature = "trusted_fused")]
444unsafe impl<A, B> TrustedFusedfor Zip<A, B>
445where
446A: TrustedFused,
447 B: TrustedFused,
448{
449}
450451#[unstable(feature = "trusted_len", issue = "37572")]
452unsafe impl<A, B> TrustedLenfor Zip<A, B>
453where
454A: TrustedLen,
455 B: TrustedLen,
456{
457}
458459impl<A, B> UncheckedIteratorfor Zip<A, B>
460where
461A: UncheckedIterator,
462 B: UncheckedIterator,
463{
464}
465466// Arbitrarily selects the left side of the zip iteration as extractable "source"
467// it would require negative trait bounds to be able to try both
468#[unstable(issue = "none", feature = "inplace_iteration")]
469unsafe impl<A, B> SourceIterfor Zip<A, B>
470where
471A: SourceIter,
472{
473type Source = A::Source;
474475#[inline]
476unsafe fn as_inner(&mut self) -> &mut A::Source {
477// SAFETY: unsafe function forwarding to unsafe function with the same requirements
478unsafe { SourceIter::as_inner(&mut self.a) }
479 }
480}
481482// Since SourceIter forwards the left hand side we do the same here
483#[unstable(issue = "none", feature = "inplace_iteration")]
484unsafe impl<A: InPlaceIterable, B> InPlaceIterablefor Zip<A, B> {
485const EXPAND_BY: Option<NonZero<usize>> = A::EXPAND_BY;
486const MERGE_BY: Option<NonZero<usize>> = A::MERGE_BY;
487}
488489#[stable(feature = "rust1", since = "1.0.0")]
490impl<A: Debug, B: Debug> Debugfor Zip<A, B> {
491fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492 ZipFmt::fmt(self, f)
493 }
494}
495496trait ZipFmt<A, B> {
497fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
498}
499500impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
501 default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish()
503 }
504}
505506impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoerce> ZipFmt<A, B>
507for Zip<A, B>
508{
509fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
510// It's *not safe* to call fmt on the contained iterators, since once
511 // we start iterating they're in strange, potentially unsafe, states.
512f.debug_struct("Zip").finish()
513 }
514}
515516/// An iterator whose items are random-accessible efficiently
517///
518/// # Safety
519///
520/// The iterator's `size_hint` must be exact and cheap to call.
521///
522/// `TrustedRandomAccessNoCoerce::size` may not be overridden.
523///
524/// All subtypes and all supertypes of `Self` must also implement `TrustedRandomAccess`.
525/// In particular, this means that types with non-invariant parameters usually can not have
526/// an impl for `TrustedRandomAccess` that depends on any trait bounds on such parameters, except
527/// for bounds that come from the respective struct/enum definition itself, or bounds involving
528/// traits that themselves come with a guarantee similar to this one.
529///
530/// If `Self: ExactSizeIterator` then `self.len()` must always produce results consistent
531/// with `self.size()`.
532///
533/// If `Self: Iterator`, then `<Self as Iterator>::__iterator_get_unchecked(&mut self, idx)`
534/// must be safe to call provided the following conditions are met.
535///
536/// 1. `0 <= idx` and `idx < self.size()`.
537/// 2. If `Self: !Clone`, then `self.__iterator_get_unchecked(idx)` is never called with the same
538/// index on `self` more than once.
539/// 3. After `self.__iterator_get_unchecked(idx)` has been called, then `self.next_back()` will
540/// only be called at most `self.size() - idx - 1` times. If `Self: Clone` and `self` is cloned,
541/// then this number is calculated for `self` and its clone individually,
542/// but `self.next_back()` calls that happened before the cloning count for both `self` and the clone.
543/// 4. After `self.__iterator_get_unchecked(idx)` has been called, then only the following methods
544/// will be called on `self` or on any new clones of `self`:
545/// * `std::clone::Clone::clone`
546/// * `std::iter::Iterator::size_hint`
547/// * `std::iter::DoubleEndedIterator::next_back`
548/// * `std::iter::ExactSizeIterator::len`
549/// * `std::iter::Iterator::__iterator_get_unchecked`
550/// * `std::iter::TrustedRandomAccessNoCoerce::size`
551/// 5. If `Self` is a subtype of `T`, then `self` is allowed to be coerced
552/// to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already
553/// been called, then no methods except for the ones listed under 4. are allowed to be called
554/// on the resulting value of type `T`, either. Multiple such coercion steps are allowed.
555/// Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is
556/// called on `self` and the resulting value of type `T` (and on further coercion results with
557/// super-supertypes) are added together and their sums must not exceed the specified bounds.
558///
559/// Further, given that these conditions are met, it must guarantee that:
560///
561/// * It does not change the value returned from `size_hint`
562/// * It must be safe to call the methods listed above on `self` after calling
563/// `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented.
564/// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`.
565/// * If `Self` is a subtype of `T`, then it must be safe to coerce `self` to `T`.
566//
567// FIXME: Clarify interaction with SourceIter/InPlaceIterable. Calling `SourceIter::as_inner`
568// after `__iterator_get_unchecked` is supposed to be allowed.
569#[doc(hidden)]
570#[unstable(feature = "trusted_random_access", issue = "none")]
571#[rustc_specialization_trait]
572pub unsafe trait TrustedRandomAccess: TrustedRandomAccessNoCoerce {}
573574/// Like [`TrustedRandomAccess`] but without any of the requirements / guarantees around
575/// coercions to supertypes after `__iterator_get_unchecked` (they aren’t allowed here!), and
576/// without the requirement that subtypes / supertypes implement `TrustedRandomAccessNoCoerce`.
577///
578/// This trait was created in PR #85874 to fix soundness issue #85873 without performance regressions.
579/// It is subject to change as we might want to build a more generally useful (for performance
580/// optimizations) and more sophisticated trait or trait hierarchy that replaces or extends
581/// [`TrustedRandomAccess`] and `TrustedRandomAccessNoCoerce`.
582#[doc(hidden)]
583#[unstable(feature = "trusted_random_access", issue = "none")]
584#[rustc_specialization_trait]
585pub unsafe trait TrustedRandomAccessNoCoerce: Sized {
586// Convenience method.
587fn size(&self) -> usize588where
589Self: Iterator,
590 {
591self.size_hint().0
592}
593/// `true` if getting an iterator element may have side effects.
594 /// Remember to take inner iterators into account.
595const MAY_HAVE_SIDE_EFFECT: bool;
596}
597598/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to
599/// know that `U: TrustedRandomAccess`.
600///
601/// ## Safety
602///
603/// Same requirements calling `get_unchecked` directly.
604#[doc(hidden)]
605#[inline]
606pub(in crate::iter::adapters) unsafe fn try_get_unchecked<I>(it: &mut I, idx: usize) -> I::Item
607where
608I: Iterator,
609{
610// SAFETY: the caller must uphold the contract for
611 // `Iterator::__iterator_get_unchecked`.
612unsafe { it.try_get_unchecked(idx) }
613}
614615unsafe trait SpecTrustedRandomAccess: Iterator {
616/// If `Self: TrustedRandomAccess`, it must be safe to call
617 /// `Iterator::__iterator_get_unchecked(self, index)`.
618unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
619}
620621unsafe impl<I: Iterator> SpecTrustedRandomAccessfor I {
622 default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item {
623{
crate::panicking::panic_fmt(format_args!("Should only be called on TrustedRandomAccess iterators"));
};panic!("Should only be called on TrustedRandomAccess iterators");
624 }
625}
626627unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccessfor I {
628#[inline]
629unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
630// SAFETY: the caller must uphold the contract for
631 // `Iterator::__iterator_get_unchecked`.
632unsafe { self.__iterator_get_unchecked(index) }
633 }
634}
635636trait SpecFold: Iterator {
637fn spec_fold<B, F>(self, init: B, f: F) -> B
638where
639Self: Sized,
640 F: FnMut(B, Self::Item) -> B;
641}
642643impl<A: Iterator, B: Iterator> SpecFoldfor Zip<A, B> {
644// Adapted from default impl from the Iterator trait
645#[inline]
646default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
647where
648F: FnMut(Acc, Self::Item) -> Acc,
649 {
650let mut accum = init;
651while let Some(x) = ZipImpl::next(&mut self) {
652 accum = f(accum, x);
653 }
654accum655 }
656}
657658impl<A: TrustedLen, B: TrustedLen> SpecFoldfor Zip<A, B> {
659#[inline]
660fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
661where
662F: FnMut(Acc, Self::Item) -> Acc,
663 {
664let mut accum = init;
665loop {
666let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 {
667 (upper, false)
668 } else {
669// Per TrustedLen contract a None upper bound means more than usize::MAX items
670(usize::MAX, true)
671 };
672673for _ in 0..upper {
674let pair =
675// SAFETY: TrustedLen guarantees that at least `upper` many items are available
676 // therefore we know they can't be None
677unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) };
678 accum = f(accum, pair);
679 }
680681if !more {
682break;
683 }
684 }
685accum686 }
687}