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
128#[doc(hidden)]
129trait ZipImpl<A, B> {
130type Item;
131fn new(a: A, b: B) -> Self;
132fn next(&mut self) -> Option<Self::Item>;
133fn size_hint(&self) -> (usize, Option<usize>);
134fn nth(&mut self, n: usize) -> Option<Self::Item>;
135fn next_back(&mut self) -> Option<Self::Item>
136where
137A: DoubleEndedIterator + ExactSizeIterator,
138 B: DoubleEndedIterator + ExactSizeIterator;
139fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
140where
141F: FnMut(Acc, Self::Item) -> Acc;
142// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
143unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item144where
145Self: Iterator + TrustedRandomAccessNoCoerce;
146}
147148// Work around limitations of specialization, requiring `default` impls to be repeated
149// in intermediary impls.
150macro_rules!zip_impl_general_defaults {
151 () => {
152 default fn new(a: A, b: B) -> Self {
153 Zip {
154 a,
155 b,
156 index: 0, // unused
157len: 0, // unused
158}
159 }
160161#[inline]
162default fn next(&mut self) -> Option<(A::Item, B::Item)> {
163let x = self.a.next()?;
164let y = self.b.next()?;
165Some((x, y))
166 }
167168#[inline]
169default fn nth(&mut self, n: usize) -> Option<Self::Item> {
170self.super_nth(n)
171 }
172173#[inline]
174default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
175where
176A: DoubleEndedIterator + ExactSizeIterator,
177 B: DoubleEndedIterator + ExactSizeIterator,
178 {
179// The function body below only uses `self.a/b.len()` and `self.a/b.next_back()`
180 // and doesn’t call `next_back` too often, so this implementation is safe in
181 // the `TrustedRandomAccessNoCoerce` specialization
182183let a_sz = self.a.len();
184let b_sz = self.b.len();
185if a_sz != b_sz {
186// Adjust a, b to equal length
187if a_sz > b_sz {
188for _ in 0..a_sz - b_sz {
189self.a.next_back();
190 }
191 } else {
192for _ in 0..b_sz - a_sz {
193self.b.next_back();
194 }
195 }
196 }
197match (self.a.next_back(), self.b.next_back()) {
198 (Some(x), Some(y)) => Some((x, y)),
199 (None, None) => None,
200_ => unreachable!(),
201 }
202 }
203 };
204}
205206// General Zip impl
207#[doc(hidden)]
208impl<A, B> ZipImpl<A, B> for Zip<A, B>
209where
210A: Iterator,
211 B: Iterator,
212{
213type Item = (A::Item, B::Item);
214215default 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! {}216217#[inline]
218default fn size_hint(&self) -> (usize, Option<usize>) {
219let (a_lower, a_upper) = self.a.size_hint();
220let (b_lower, b_upper) = self.b.size_hint();
221222let lower = cmp::min(a_lower, b_lower);
223224let upper = match (a_upper, b_upper) {
225 (Some(x), Some(y)) => Some(cmp::min(x, y)),
226 (Some(x), None) => Some(x),
227 (None, Some(y)) => Some(y),
228 (None, None) => None,
229 };
230231 (lower, upper)
232 }
233234 default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item235where
236Self: TrustedRandomAccessNoCoerce,
237 {
238{
crate::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Always specialized")));
};unreachable!("Always specialized");
239 }
240241#[inline]
242default fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
243where
244F: FnMut(Acc, Self::Item) -> Acc,
245 {
246 SpecFold::spec_fold(self, init, f)
247 }
248}
249250#[doc(hidden)]
251impl<A, B> ZipImpl<A, B> for Zip<A, B>
252where
253A: TrustedRandomAccessNoCoerce + Iterator,
254 B: TrustedRandomAccessNoCoerce + Iterator,
255{
256default 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! {}257258#[inline]
259default fn size_hint(&self) -> (usize, Option<usize>) {
260let size = cmp::min(self.a.size(), self.b.size());
261 (size, Some(size))
262 }
263264#[inline]
265unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
266let idx = self.index + idx;
267// SAFETY: the caller must uphold the contract for
268 // `Iterator::__iterator_get_unchecked`.
269unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
270 }
271272#[inline]
273fn fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
274where
275F: FnMut(Acc, Self::Item) -> Acc,
276 {
277let mut accum = init;
278let len = ZipImpl::size_hint(&self).0;
279for i in 0..len {
280// SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to
281 // calculate the length and then use that to do unchecked iteration.
282 // fold consumes the iterator so we don't need to fixup any state.
283unsafe {
284 accum = f(accum, self.get_unchecked(i));
285 }
286 }
287accum288 }
289}
290291#[doc(hidden)]
292impl<A, B> ZipImpl<A, B> for Zip<A, B>
293where
294A: TrustedRandomAccess + Iterator,
295 B: TrustedRandomAccess + Iterator,
296{
297fn new(a: A, b: B) -> Self {
298let len = cmp::min(a.size(), b.size());
299Zip { a, b, index: 0, len }
300 }
301302#[inline]
303fn next(&mut self) -> Option<(A::Item, B::Item)> {
304if self.index < self.len {
305let i = self.index;
306// since get_unchecked executes code which can panic we increment the counters beforehand
307 // so that the same index won't be accessed twice, as required by TrustedRandomAccess
308self.index += 1;
309// SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
310unsafe {
311Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
312 }
313 } else {
314None315 }
316 }
317318#[inline]
319fn size_hint(&self) -> (usize, Option<usize>) {
320let len = self.len - self.index;
321 (len, Some(len))
322 }
323324#[inline]
325fn nth(&mut self, n: usize) -> Option<Self::Item> {
326let delta = cmp::min(n, self.len - self.index);
327let end = self.index + delta;
328while self.index < end {
329let i = self.index;
330// since get_unchecked executes code which can panic we increment the counters beforehand
331 // so that the same index won't be accessed twice, as required by TrustedRandomAccess
332self.index += 1;
333if A::MAY_HAVE_SIDE_EFFECT {
334// SAFETY: the usage of `cmp::min` to calculate `delta`
335 // ensures that `end` is smaller than or equal to `self.len`,
336 // so `i` is also smaller than `self.len`.
337unsafe {
338self.a.__iterator_get_unchecked(i);
339 }
340 }
341if B::MAY_HAVE_SIDE_EFFECT {
342// SAFETY: same as above.
343unsafe {
344self.b.__iterator_get_unchecked(i);
345 }
346 }
347 }
348349self.super_nth(n - delta)
350 }
351352#[inline]
353fn next_back(&mut self) -> Option<(A::Item, B::Item)>
354where
355A: DoubleEndedIterator + ExactSizeIterator,
356 B: DoubleEndedIterator + ExactSizeIterator,
357 {
358// No effects when the iterator is exhausted, to reduce the number of
359 // cases the unsafe code has to handle.
360 // See #137255 for a case where where too many epicycles lead to unsoundness.
361if self.index < self.len {
362let old_len = self.len;
363364// since get_unchecked and the side-effecting code can execute user code
365 // which can panic we decrement the counter beforehand
366 // so that the same index won't be accessed twice, as required by TrustedRandomAccess.
367 // Additionally this will ensure that the side-effects code won't run a second time.
368self.len -= 1;
369370// Adjust a, b to equal length if we're iterating backwards.
371if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
372// note if some forward-iteration already happened then these aren't the real
373 // remaining lengths of the inner iterators, so we have to relate them to
374 // Zip's internal length-tracking.
375let sz_a = self.a.size();
376let sz_b = self.b.size();
377// This condition can and must only be true on the first `next_back` call,
378 // otherwise we will break the restriction on calls to `self.next_back()`
379 // after calling `get_unchecked()`.
380if sz_a != sz_b && (old_len == sz_a || old_len == sz_b) {
381if A::MAY_HAVE_SIDE_EFFECT && sz_a > old_len {
382for _ in 0..sz_a - old_len {
383self.a.next_back();
384 }
385 }
386if B::MAY_HAVE_SIDE_EFFECT && sz_b > old_len {
387for _ in 0..sz_b - old_len {
388self.b.next_back();
389 }
390 }
391if 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());
392 }
393 }
394let i = self.len;
395// SAFETY: `i` is smaller than the previous value of `self.len`,
396 // which is also smaller than or equal to `self.a.len()` and `self.b.len()`
397unsafe {
398Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
399 }
400 } else {
401None402 }
403 }
404}
405406#[stable(feature = "rust1", since = "1.0.0")]
407impl<A, B> ExactSizeIteratorfor Zip<A, B>
408where
409A: ExactSizeIterator,
410 B: ExactSizeIterator,
411{
412}
413414#[doc(hidden)]
415#[unstable(feature = "trusted_random_access", issue = "none")]
416unsafe impl<A, B> TrustedRandomAccessfor Zip<A, B>
417where
418A: TrustedRandomAccess,
419 B: TrustedRandomAccess,
420{
421}
422423#[doc(hidden)]
424#[unstable(feature = "trusted_random_access", issue = "none")]
425unsafe impl<A, B> TrustedRandomAccessNoCoercefor Zip<A, B>
426where
427A: TrustedRandomAccessNoCoerce,
428 B: TrustedRandomAccessNoCoerce,
429{
430const MAY_HAVE_SIDE_EFFECT: bool = A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT;
431}
432433#[stable(feature = "fused", since = "1.26.0")]
434impl<A, B> FusedIteratorfor Zip<A, B>
435where
436A: FusedIterator,
437 B: FusedIterator,
438{
439}
440441#[unstable(issue = "none", feature = "trusted_fused")]
442unsafe impl<A, B> TrustedFusedfor Zip<A, B>
443where
444A: TrustedFused,
445 B: TrustedFused,
446{
447}
448449#[unstable(feature = "trusted_len", issue = "37572")]
450unsafe impl<A, B> TrustedLenfor Zip<A, B>
451where
452A: TrustedLen,
453 B: TrustedLen,
454{
455}
456457// Arbitrarily selects the left side of the zip iteration as extractable "source"
458// it would require negative trait bounds to be able to try both
459#[unstable(issue = "none", feature = "inplace_iteration")]
460unsafe impl<A, B> SourceIterfor Zip<A, B>
461where
462A: SourceIter,
463{
464type Source = A::Source;
465466#[inline]
467unsafe fn as_inner(&mut self) -> &mut A::Source {
468// SAFETY: unsafe function forwarding to unsafe function with the same requirements
469unsafe { SourceIter::as_inner(&mut self.a) }
470 }
471}
472473// Since SourceIter forwards the left hand side we do the same here
474#[unstable(issue = "none", feature = "inplace_iteration")]
475unsafe impl<A: InPlaceIterable, B> InPlaceIterablefor Zip<A, B> {
476const EXPAND_BY: Option<NonZero<usize>> = A::EXPAND_BY;
477const MERGE_BY: Option<NonZero<usize>> = A::MERGE_BY;
478}
479480#[stable(feature = "rust1", since = "1.0.0")]
481impl<A: Debug, B: Debug> Debugfor Zip<A, B> {
482fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483 ZipFmt::fmt(self, f)
484 }
485}
486487trait ZipFmt<A, B> {
488fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
489}
490491impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
492 default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish()
494 }
495}
496497impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoerce> ZipFmt<A, B>
498for Zip<A, B>
499{
500fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501// It's *not safe* to call fmt on the contained iterators, since once
502 // we start iterating they're in strange, potentially unsafe, states.
503f.debug_struct("Zip").finish()
504 }
505}
506507/// An iterator whose items are random-accessible efficiently
508///
509/// # Safety
510///
511/// The iterator's `size_hint` must be exact and cheap to call.
512///
513/// `TrustedRandomAccessNoCoerce::size` may not be overridden.
514///
515/// All subtypes and all supertypes of `Self` must also implement `TrustedRandomAccess`.
516/// In particular, this means that types with non-invariant parameters usually can not have
517/// an impl for `TrustedRandomAccess` that depends on any trait bounds on such parameters, except
518/// for bounds that come from the respective struct/enum definition itself, or bounds involving
519/// traits that themselves come with a guarantee similar to this one.
520///
521/// If `Self: ExactSizeIterator` then `self.len()` must always produce results consistent
522/// with `self.size()`.
523///
524/// If `Self: Iterator`, then `<Self as Iterator>::__iterator_get_unchecked(&mut self, idx)`
525/// must be safe to call provided the following conditions are met.
526///
527/// 1. `0 <= idx` and `idx < self.size()`.
528/// 2. If `Self: !Clone`, then `self.__iterator_get_unchecked(idx)` is never called with the same
529/// index on `self` more than once.
530/// 3. After `self.__iterator_get_unchecked(idx)` has been called, then `self.next_back()` will
531/// only be called at most `self.size() - idx - 1` times. If `Self: Clone` and `self` is cloned,
532/// then this number is calculated for `self` and its clone individually,
533/// but `self.next_back()` calls that happened before the cloning count for both `self` and the clone.
534/// 4. After `self.__iterator_get_unchecked(idx)` has been called, then only the following methods
535/// will be called on `self` or on any new clones of `self`:
536/// * `std::clone::Clone::clone`
537/// * `std::iter::Iterator::size_hint`
538/// * `std::iter::DoubleEndedIterator::next_back`
539/// * `std::iter::ExactSizeIterator::len`
540/// * `std::iter::Iterator::__iterator_get_unchecked`
541/// * `std::iter::TrustedRandomAccessNoCoerce::size`
542/// 5. If `Self` is a subtype of `T`, then `self` is allowed to be coerced
543/// to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already
544/// been called, then no methods except for the ones listed under 4. are allowed to be called
545/// on the resulting value of type `T`, either. Multiple such coercion steps are allowed.
546/// Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is
547/// called on `self` and the resulting value of type `T` (and on further coercion results with
548/// super-supertypes) are added together and their sums must not exceed the specified bounds.
549///
550/// Further, given that these conditions are met, it must guarantee that:
551///
552/// * It does not change the value returned from `size_hint`
553/// * It must be safe to call the methods listed above on `self` after calling
554/// `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented.
555/// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`.
556/// * If `Self` is a subtype of `T`, then it must be safe to coerce `self` to `T`.
557//
558// FIXME: Clarify interaction with SourceIter/InPlaceIterable. Calling `SourceIter::as_inner`
559// after `__iterator_get_unchecked` is supposed to be allowed.
560#[doc(hidden)]
561#[unstable(feature = "trusted_random_access", issue = "none")]
562#[rustc_specialization_trait]
563pub unsafe trait TrustedRandomAccess: TrustedRandomAccessNoCoerce {}
564565/// Like [`TrustedRandomAccess`] but without any of the requirements / guarantees around
566/// coercions to supertypes after `__iterator_get_unchecked` (they aren’t allowed here!), and
567/// without the requirement that subtypes / supertypes implement `TrustedRandomAccessNoCoerce`.
568///
569/// This trait was created in PR #85874 to fix soundness issue #85873 without performance regressions.
570/// It is subject to change as we might want to build a more generally useful (for performance
571/// optimizations) and more sophisticated trait or trait hierarchy that replaces or extends
572/// [`TrustedRandomAccess`] and `TrustedRandomAccessNoCoerce`.
573#[doc(hidden)]
574#[unstable(feature = "trusted_random_access", issue = "none")]
575#[rustc_specialization_trait]
576pub unsafe trait TrustedRandomAccessNoCoerce: Sized {
577// Convenience method.
578fn size(&self) -> usize579where
580Self: Iterator,
581 {
582self.size_hint().0
583}
584/// `true` if getting an iterator element may have side effects.
585 /// Remember to take inner iterators into account.
586const MAY_HAVE_SIDE_EFFECT: bool;
587}
588589/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to
590/// know that `U: TrustedRandomAccess`.
591///
592/// ## Safety
593///
594/// Same requirements calling `get_unchecked` directly.
595#[doc(hidden)]
596#[inline]
597pub(in crate::iter::adapters) unsafe fn try_get_unchecked<I>(it: &mut I, idx: usize) -> I::Item
598where
599I: Iterator,
600{
601// SAFETY: the caller must uphold the contract for
602 // `Iterator::__iterator_get_unchecked`.
603unsafe { it.try_get_unchecked(idx) }
604}
605606unsafe trait SpecTrustedRandomAccess: Iterator {
607/// If `Self: TrustedRandomAccess`, it must be safe to call
608 /// `Iterator::__iterator_get_unchecked(self, index)`.
609unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
610}
611612unsafe impl<I: Iterator> SpecTrustedRandomAccessfor I {
613 default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item {
614{
crate::panicking::panic_fmt(format_args!("Should only be called on TrustedRandomAccess iterators"));
};panic!("Should only be called on TrustedRandomAccess iterators");
615 }
616}
617618unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccessfor I {
619#[inline]
620unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
621// SAFETY: the caller must uphold the contract for
622 // `Iterator::__iterator_get_unchecked`.
623unsafe { self.__iterator_get_unchecked(index) }
624 }
625}
626627trait SpecFold: Iterator {
628fn spec_fold<B, F>(self, init: B, f: F) -> B
629where
630Self: Sized,
631 F: FnMut(B, Self::Item) -> B;
632}
633634impl<A: Iterator, B: Iterator> SpecFoldfor Zip<A, B> {
635// Adapted from default impl from the Iterator trait
636#[inline]
637default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
638where
639F: FnMut(Acc, Self::Item) -> Acc,
640 {
641let mut accum = init;
642while let Some(x) = ZipImpl::next(&mut self) {
643 accum = f(accum, x);
644 }
645accum646 }
647}
648649impl<A: TrustedLen, B: TrustedLen> SpecFoldfor Zip<A, B> {
650#[inline]
651fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
652where
653F: FnMut(Acc, Self::Item) -> Acc,
654 {
655let mut accum = init;
656loop {
657let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 {
658 (upper, false)
659 } else {
660// Per TrustedLen contract a None upper bound means more than usize::MAX items
661(usize::MAX, true)
662 };
663664for _ in 0..upper {
665let pair =
666// SAFETY: TrustedLen guarantees that at least `upper` many items are available
667 // therefore we know they can't be None
668unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) };
669 accum = f(accum, pair);
670 }
671672if !more {
673break;
674 }
675 }
676accum677 }
678}