1use crate::cmp;
2use crate::fmt::{self, Debug};
3use crate::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen};
4use crate::num::NonZero;
56/// An iterator that iterates two other iterators simultaneously.
7///
8/// This `struct` is created by [`zip`] or [`Iterator::zip`].
9/// See their documentation for more.
10#[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)]
11#[must_use = "iterators are lazy and do nothing unless consumed"]
12#[stable(feature = "rust1", since = "1.0.0")]
13pub struct Zip<A, B> {
14 a: A,
15 b: B,
16// index, len and a_len are only used by the specialized version of zip
17index: usize,
18 len: usize,
19}
20impl<A: Iterator, B: Iterator> Zip<A, B> {
21pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
22 ZipImpl::new(a, b)
23 }
24fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
25while let Some(x) = Iterator::next(self) {
26if n == 0 {
27return Some(x);
28 }
29 n -= 1;
30 }
31None32 }
33}
3435/// Converts the arguments to iterators and zips them.
36///
37/// See the documentation of [`Iterator::zip`] for more.
38///
39/// # Examples
40///
41/// ```
42/// use std::iter::zip;
43///
44/// let xs = [1, 2, 3];
45/// let ys = [4, 5, 6];
46///
47/// let mut iter = zip(xs, ys);
48///
49/// assert_eq!(iter.next().unwrap(), (1, 4));
50/// assert_eq!(iter.next().unwrap(), (2, 5));
51/// assert_eq!(iter.next().unwrap(), (3, 6));
52/// assert!(iter.next().is_none());
53///
54/// // Nested zips are also possible:
55/// let zs = [7, 8, 9];
56///
57/// let mut iter = zip(zip(xs, ys), zs);
58///
59/// assert_eq!(iter.next().unwrap(), ((1, 4), 7));
60/// assert_eq!(iter.next().unwrap(), ((2, 5), 8));
61/// assert_eq!(iter.next().unwrap(), ((3, 6), 9));
62/// assert!(iter.next().is_none());
63/// ```
64#[stable(feature = "iter_zip", since = "1.59.0")]
65pub fn zip<A, B>(a: A, b: B) -> Zip<A::IntoIter, B::IntoIter>
66where
67A: IntoIterator,
68 B: IntoIterator,
69{
70 ZipImpl::new(a.into_iter(), b.into_iter())
71}
7273#[stable(feature = "rust1", since = "1.0.0")]
74impl<A, B> Iteratorfor Zip<A, B>
75where
76A: Iterator,
77 B: Iterator,
78{
79type Item = (A::Item, B::Item);
8081#[inline]
82fn next(&mut self) -> Option<Self::Item> {
83 ZipImpl::next(self)
84 }
8586#[inline]
87fn size_hint(&self) -> (usize, Option<usize>) {
88 ZipImpl::size_hint(self)
89 }
9091#[inline]
92fn nth(&mut self, n: usize) -> Option<Self::Item> {
93 ZipImpl::nth(self, n)
94 }
9596#[inline]
97fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
98where
99F: FnMut(Acc, Self::Item) -> Acc,
100 {
101 ZipImpl::fold(self, init, f)
102 }
103104#[inline]
105unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
106where
107Self: TrustedRandomAccessNoCoerce,
108 {
109// SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
110 // requirements as `Iterator::__iterator_get_unchecked`.
111unsafe { ZipImpl::get_unchecked(self, idx) }
112 }
113}
114115#[stable(feature = "rust1", since = "1.0.0")]
116impl<A, B> DoubleEndedIteratorfor Zip<A, B>
117where
118A: DoubleEndedIterator + ExactSizeIterator,
119 B: DoubleEndedIterator + ExactSizeIterator,
120{
121#[inline]
122fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
123 ZipImpl::next_back(self)
124 }
125}
126127// Zip specialization trait
128trait ZipImpl<A, B> {
129type Item;
130fn new(a: A, b: B) -> Self;
131fn next(&mut self) -> Option<Self::Item>;
132fn size_hint(&self) -> (usize, Option<usize>);
133fn nth(&mut self, n: usize) -> Option<Self::Item>;
134fn next_back(&mut self) -> Option<Self::Item>
135where
136A: DoubleEndedIterator + ExactSizeIterator,
137 B: DoubleEndedIterator + ExactSizeIterator;
138fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
139where
140F: FnMut(Acc, Self::Item) -> Acc;
141// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
142unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item143where
144Self: Iterator + TrustedRandomAccessNoCoerce;
145}
146147// Work around limitations of specialization, requiring `default` impls to be repeated
148// in intermediary impls.
149macro_rules!zip_impl_general_defaults {
150 () => {
151 default fn new(a: A, b: B) -> Self {
152 Zip {
153 a,
154 b,
155 index: 0, // unused
156len: 0, // unused
157}
158 }
159160#[inline]
161default fn next(&mut self) -> Option<(A::Item, B::Item)> {
162let x = self.a.next()?;
163let y = self.b.next()?;
164Some((x, y))
165 }
166167#[inline]
168default fn nth(&mut self, n: usize) -> Option<Self::Item> {
169self.super_nth(n)
170 }
171172#[inline]
173default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
174where
175A: DoubleEndedIterator + ExactSizeIterator,
176 B: DoubleEndedIterator + ExactSizeIterator,
177 {
178// The function body below only uses `self.a/b.len()` and `self.a/b.next_back()`
179 // and doesn’t call `next_back` too often, so this implementation is safe in
180 // the `TrustedRandomAccessNoCoerce` specialization
181182let a_sz = self.a.len();
183let b_sz = self.b.len();
184if a_sz != b_sz {
185// Adjust a, b to equal length
186if a_sz > b_sz {
187for _ in 0..a_sz - b_sz {
188self.a.next_back();
189 }
190 } else {
191for _ in 0..b_sz - a_sz {
192self.b.next_back();
193 }
194 }
195 }
196match (self.a.next_back(), self.b.next_back()) {
197 (Some(x), Some(y)) => Some((x, y)),
198 (None, None) => None,
199_ => unreachable!(),
200 }
201 }
202 };
203}
204205// General Zip impl
206impl<A, B> ZipImpl<A, B> for Zip<A, B>
207where
208A: Iterator,
209 B: Iterator,
210{
211type Item = (A::Item, B::Item);
212213default fn new(a: A, b: B) -> Self { Zip { a, b, index: 0, len: 0 } }
#[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::Item> {
self.super_nth(n)
}
#[inline]
default fn next_back(&mut self) -> Option<(A::Item, B::Item)> where
A: DoubleEndedIterator + ExactSizeIterator, B: DoubleEndedIterator +
ExactSizeIterator {
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! {}214215#[inline]
216default fn size_hint(&self) -> (usize, Option<usize>) {
217let (a_lower, a_upper) = self.a.size_hint();
218let (b_lower, b_upper) = self.b.size_hint();
219220let lower = cmp::min(a_lower, b_lower);
221222let upper = match (a_upper, b_upper) {
223 (Some(x), Some(y)) => Some(cmp::min(x, y)),
224 (Some(x), None) => Some(x),
225 (None, Some(y)) => Some(y),
226 (None, None) => None,
227 };
228229 (lower, upper)
230 }
231232 default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item233where
234Self: TrustedRandomAccessNoCoerce,
235 {
236{
crate::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Always specialized")));
};unreachable!("Always specialized");
237 }
238239#[inline]
240default fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
241where
242F: FnMut(Acc, Self::Item) -> Acc,
243 {
244 SpecFold::spec_fold(self, init, f)
245 }
246}
247248impl<A, B> ZipImpl<A, B> for Zip<A, B>
249where
250A: TrustedRandomAccessNoCoerce + Iterator,
251 B: TrustedRandomAccessNoCoerce + Iterator,
252{
253default fn new(a: A, b: B) -> Self { Zip { a, b, index: 0, len: 0 } }
#[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::Item> {
self.super_nth(n)
}
#[inline]
default fn next_back(&mut self) -> Option<(A::Item, B::Item)> where
A: DoubleEndedIterator + ExactSizeIterator, B: DoubleEndedIterator +
ExactSizeIterator {
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! {}254255#[inline]
256default fn size_hint(&self) -> (usize, Option<usize>) {
257let size = cmp::min(self.a.size(), self.b.size());
258 (size, Some(size))
259 }
260261#[inline]
262unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
263let idx = self.index + idx;
264// SAFETY: the caller must uphold the contract for
265 // `Iterator::__iterator_get_unchecked`.
266unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
267 }
268269#[inline]
270fn fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
271where
272F: FnMut(Acc, Self::Item) -> Acc,
273 {
274let mut accum = init;
275let len = ZipImpl::size_hint(&self).0;
276for i in 0..len {
277// SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to
278 // calculate the length and then use that to do unchecked iteration.
279 // fold consumes the iterator so we don't need to fixup any state.
280unsafe {
281 accum = f(accum, self.get_unchecked(i));
282 }
283 }
284accum285 }
286}
287288impl<A, B> ZipImpl<A, B> for Zip<A, B>
289where
290A: TrustedRandomAccess + Iterator,
291 B: TrustedRandomAccess + Iterator,
292{
293fn new(a: A, b: B) -> Self {
294let len = cmp::min(a.size(), b.size());
295Zip { a, b, index: 0, len }
296 }
297298#[inline]
299fn next(&mut self) -> Option<(A::Item, B::Item)> {
300if self.index < self.len {
301let i = self.index;
302// since get_unchecked executes code which can panic we increment the counters beforehand
303 // so that the same index won't be accessed twice, as required by TrustedRandomAccess
304self.index += 1;
305// SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
306unsafe {
307Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
308 }
309 } else {
310None311 }
312 }
313314#[inline]
315fn size_hint(&self) -> (usize, Option<usize>) {
316let len = self.len - self.index;
317 (len, Some(len))
318 }
319320#[inline]
321fn nth(&mut self, n: usize) -> Option<Self::Item> {
322let delta = cmp::min(n, self.len - self.index);
323let end = self.index + delta;
324while self.index < end {
325let i = self.index;
326// since get_unchecked executes code which can panic we increment the counters beforehand
327 // so that the same index won't be accessed twice, as required by TrustedRandomAccess
328self.index += 1;
329if A::MAY_HAVE_SIDE_EFFECT {
330// SAFETY: the usage of `cmp::min` to calculate `delta`
331 // ensures that `end` is smaller than or equal to `self.len`,
332 // so `i` is also smaller than `self.len`.
333unsafe {
334self.a.__iterator_get_unchecked(i);
335 }
336 }
337if B::MAY_HAVE_SIDE_EFFECT {
338// SAFETY: same as above.
339unsafe {
340self.b.__iterator_get_unchecked(i);
341 }
342 }
343 }
344345self.super_nth(n - delta)
346 }
347348#[inline]
349fn next_back(&mut self) -> Option<(A::Item, B::Item)>
350where
351A: DoubleEndedIterator + ExactSizeIterator,
352 B: DoubleEndedIterator + ExactSizeIterator,
353 {
354// No effects when the iterator is exhausted, to reduce the number of
355 // cases the unsafe code has to handle.
356 // See #137255 for a case where where too many epicycles lead to unsoundness.
357if self.index < self.len {
358let old_len = self.len;
359360// since get_unchecked and the side-effecting code can execute user code
361 // which can panic we decrement the counter beforehand
362 // so that the same index won't be accessed twice, as required by TrustedRandomAccess.
363 // Additionally this will ensure that the side-effects code won't run a second time.
364self.len -= 1;
365366// Adjust a, b to equal length if we're iterating backwards.
367if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
368// note if some forward-iteration already happened then these aren't the real
369 // remaining lengths of the inner iterators, so we have to relate them to
370 // Zip's internal length-tracking.
371let sz_a = self.a.size();
372let sz_b = self.b.size();
373// This condition can and must only be true on the first `next_back` call,
374 // otherwise we will break the restriction on calls to `self.next_back()`
375 // after calling `get_unchecked()`.
376if sz_a != sz_b && (old_len == sz_a || old_len == sz_b) {
377if A::MAY_HAVE_SIDE_EFFECT && sz_a > old_len {
378for _ in 0..sz_a - old_len {
379self.a.next_back();
380 }
381 }
382if B::MAY_HAVE_SIDE_EFFECT && sz_b > old_len {
383for _ in 0..sz_b - old_len {
384self.b.next_back();
385 }
386 }
387if 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());
388 }
389 }
390let i = self.len;
391// SAFETY: `i` is smaller than the previous value of `self.len`,
392 // which is also smaller than or equal to `self.a.len()` and `self.b.len()`
393unsafe {
394Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
395 }
396 } else {
397None398 }
399 }
400}
401402#[stable(feature = "rust1", since = "1.0.0")]
403impl<A, B> ExactSizeIteratorfor Zip<A, B>
404where
405A: ExactSizeIterator,
406 B: ExactSizeIterator,
407{
408}
409410#[doc(hidden)]
411#[unstable(feature = "trusted_random_access", issue = "none")]
412unsafe impl<A, B> TrustedRandomAccessfor Zip<A, B>
413where
414A: TrustedRandomAccess,
415 B: TrustedRandomAccess,
416{
417}
418419#[doc(hidden)]
420#[unstable(feature = "trusted_random_access", issue = "none")]
421unsafe impl<A, B> TrustedRandomAccessNoCoercefor Zip<A, B>
422where
423A: TrustedRandomAccessNoCoerce,
424 B: TrustedRandomAccessNoCoerce,
425{
426const MAY_HAVE_SIDE_EFFECT: bool = A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT;
427}
428429#[stable(feature = "fused", since = "1.26.0")]
430impl<A, B> FusedIteratorfor Zip<A, B>
431where
432A: FusedIterator,
433 B: FusedIterator,
434{
435}
436437#[unstable(issue = "none", feature = "trusted_fused")]
438unsafe impl<A, B> TrustedFusedfor Zip<A, B>
439where
440A: TrustedFused,
441 B: TrustedFused,
442{
443}
444445#[unstable(feature = "trusted_len", issue = "37572")]
446unsafe impl<A, B> TrustedLenfor Zip<A, B>
447where
448A: TrustedLen,
449 B: TrustedLen,
450{
451}
452453// Arbitrarily selects the left side of the zip iteration as extractable "source"
454// it would require negative trait bounds to be able to try both
455#[unstable(issue = "none", feature = "inplace_iteration")]
456unsafe impl<A, B> SourceIterfor Zip<A, B>
457where
458A: SourceIter,
459{
460type Source = A::Source;
461462#[inline]
463unsafe fn as_inner(&mut self) -> &mut A::Source {
464// SAFETY: unsafe function forwarding to unsafe function with the same requirements
465unsafe { SourceIter::as_inner(&mut self.a) }
466 }
467}
468469// Since SourceIter forwards the left hand side we do the same here
470#[unstable(issue = "none", feature = "inplace_iteration")]
471unsafe impl<A: InPlaceIterable, B> InPlaceIterablefor Zip<A, B> {
472const EXPAND_BY: Option<NonZero<usize>> = A::EXPAND_BY;
473const MERGE_BY: Option<NonZero<usize>> = A::MERGE_BY;
474}
475476#[stable(feature = "rust1", since = "1.0.0")]
477impl<A: Debug, B: Debug> Debugfor Zip<A, B> {
478fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
479 ZipFmt::fmt(self, f)
480 }
481}
482483trait ZipFmt<A, B> {
484fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
485}
486487impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
488 default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
489f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish()
490 }
491}
492493impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoerce> ZipFmt<A, B>
494for Zip<A, B>
495{
496fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497// It's *not safe* to call fmt on the contained iterators, since once
498 // we start iterating they're in strange, potentially unsafe, states.
499f.debug_struct("Zip").finish()
500 }
501}
502503/// An iterator whose items are random-accessible efficiently
504///
505/// # Safety
506///
507/// The iterator's `size_hint` must be exact and cheap to call.
508///
509/// `TrustedRandomAccessNoCoerce::size` may not be overridden.
510///
511/// All subtypes and all supertypes of `Self` must also implement `TrustedRandomAccess`.
512/// In particular, this means that types with non-invariant parameters usually can not have
513/// an impl for `TrustedRandomAccess` that depends on any trait bounds on such parameters, except
514/// for bounds that come from the respective struct/enum definition itself, or bounds involving
515/// traits that themselves come with a guarantee similar to this one.
516///
517/// If `Self: ExactSizeIterator` then `self.len()` must always produce results consistent
518/// with `self.size()`.
519///
520/// If `Self: Iterator`, then `<Self as Iterator>::__iterator_get_unchecked(&mut self, idx)`
521/// must be safe to call provided the following conditions are met.
522///
523/// 1. `0 <= idx` and `idx < self.size()`.
524/// 2. If `Self: !Clone`, then `self.__iterator_get_unchecked(idx)` is never called with the same
525/// index on `self` more than once.
526/// 3. After `self.__iterator_get_unchecked(idx)` has been called, then `self.next_back()` will
527/// only be called at most `self.size() - idx - 1` times. If `Self: Clone` and `self` is cloned,
528/// then this number is calculated for `self` and its clone individually,
529/// but `self.next_back()` calls that happened before the cloning count for both `self` and the clone.
530/// 4. After `self.__iterator_get_unchecked(idx)` has been called, then only the following methods
531/// will be called on `self` or on any new clones of `self`:
532/// * `std::clone::Clone::clone`
533/// * `std::iter::Iterator::size_hint`
534/// * `std::iter::DoubleEndedIterator::next_back`
535/// * `std::iter::ExactSizeIterator::len`
536/// * `std::iter::Iterator::__iterator_get_unchecked`
537/// * `std::iter::TrustedRandomAccessNoCoerce::size`
538/// 5. If `Self` is a subtype of `T`, then `self` is allowed to be coerced
539/// to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already
540/// been called, then no methods except for the ones listed under 4. are allowed to be called
541/// on the resulting value of type `T`, either. Multiple such coercion steps are allowed.
542/// Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is
543/// called on `self` and the resulting value of type `T` (and on further coercion results with
544/// super-supertypes) are added together and their sums must not exceed the specified bounds.
545///
546/// Further, given that these conditions are met, it must guarantee that:
547///
548/// * It does not change the value returned from `size_hint`
549/// * It must be safe to call the methods listed above on `self` after calling
550/// `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented.
551/// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`.
552/// * If `Self` is a subtype of `T`, then it must be safe to coerce `self` to `T`.
553//
554// FIXME: Clarify interaction with SourceIter/InPlaceIterable. Calling `SourceIter::as_inner`
555// after `__iterator_get_unchecked` is supposed to be allowed.
556#[doc(hidden)]
557#[unstable(feature = "trusted_random_access", issue = "none")]
558#[rustc_specialization_trait]
559pub unsafe trait TrustedRandomAccess: TrustedRandomAccessNoCoerce {}
560561/// Like [`TrustedRandomAccess`] but without any of the requirements / guarantees around
562/// coercions to supertypes after `__iterator_get_unchecked` (they aren’t allowed here!), and
563/// without the requirement that subtypes / supertypes implement `TrustedRandomAccessNoCoerce`.
564///
565/// This trait was created in PR #85874 to fix soundness issue #85873 without performance regressions.
566/// It is subject to change as we might want to build a more generally useful (for performance
567/// optimizations) and more sophisticated trait or trait hierarchy that replaces or extends
568/// [`TrustedRandomAccess`] and `TrustedRandomAccessNoCoerce`.
569#[doc(hidden)]
570#[unstable(feature = "trusted_random_access", issue = "none")]
571#[rustc_specialization_trait]
572pub unsafe trait TrustedRandomAccessNoCoerce: Sized {
573// Convenience method.
574fn size(&self) -> usize575where
576Self: Iterator,
577 {
578self.size_hint().0
579}
580/// `true` if getting an iterator element may have side effects.
581 /// Remember to take inner iterators into account.
582const MAY_HAVE_SIDE_EFFECT: bool;
583}
584585/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to
586/// know that `U: TrustedRandomAccess`.
587///
588/// ## Safety
589///
590/// Same requirements calling `get_unchecked` directly.
591#[doc(hidden)]
592#[inline]
593pub(in crate::iter::adapters) unsafe fn try_get_unchecked<I>(it: &mut I, idx: usize) -> I::Item
594where
595I: Iterator,
596{
597// SAFETY: the caller must uphold the contract for
598 // `Iterator::__iterator_get_unchecked`.
599unsafe { it.try_get_unchecked(idx) }
600}
601602unsafe trait SpecTrustedRandomAccess: Iterator {
603/// If `Self: TrustedRandomAccess`, it must be safe to call
604 /// `Iterator::__iterator_get_unchecked(self, index)`.
605unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
606}
607608unsafe impl<I: Iterator> SpecTrustedRandomAccessfor I {
609 default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item {
610{
crate::panicking::panic_fmt(format_args!("Should only be called on TrustedRandomAccess iterators"));
};panic!("Should only be called on TrustedRandomAccess iterators");
611 }
612}
613614unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccessfor I {
615#[inline]
616unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
617// SAFETY: the caller must uphold the contract for
618 // `Iterator::__iterator_get_unchecked`.
619unsafe { self.__iterator_get_unchecked(index) }
620 }
621}
622623trait SpecFold: Iterator {
624fn spec_fold<B, F>(self, init: B, f: F) -> B
625where
626Self: Sized,
627 F: FnMut(B, Self::Item) -> B;
628}
629630impl<A: Iterator, B: Iterator> SpecFoldfor Zip<A, B> {
631// Adapted from default impl from the Iterator trait
632#[inline]
633default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
634where
635F: FnMut(Acc, Self::Item) -> Acc,
636 {
637let mut accum = init;
638while let Some(x) = ZipImpl::next(&mut self) {
639 accum = f(accum, x);
640 }
641accum642 }
643}
644645impl<A: TrustedLen, B: TrustedLen> SpecFoldfor Zip<A, B> {
646#[inline]
647fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
648where
649F: FnMut(Acc, Self::Item) -> Acc,
650 {
651let mut accum = init;
652loop {
653let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 {
654 (upper, false)
655 } else {
656// Per TrustedLen contract a None upper bound means more than usize::MAX items
657(usize::MAX, true)
658 };
659660for _ in 0..upper {
661let pair =
662// SAFETY: TrustedLen guarantees that at least `upper` many items are available
663 // therefore we know they can't be None
664unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) };
665 accum = f(accum, pair);
666 }
667668if !more {
669break;
670 }
671 }
672accum673 }
674}