9494 ZipImpl :: nth ( self , n)
9595 }
9696
97+ #[ inline]
98+ fn fold < Acc , F > ( self , init : Acc , f : F ) -> Acc
99+ where
100+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
101+ {
102+ ZipImpl :: fold ( self , init, f)
103+ }
104+
97105 #[ inline]
98106 unsafe fn __iterator_get_unchecked ( & mut self , idx : usize ) -> Self :: Item
99107 where
@@ -129,6 +137,9 @@ trait ZipImpl<A, B> {
129137 where
130138 A : DoubleEndedIterator + ExactSizeIterator ,
131139 B : DoubleEndedIterator + ExactSizeIterator ;
140+ fn fold < Acc , F > ( self , init : Acc , f : F ) -> Acc
141+ where
142+ F : FnMut ( Acc , Self :: Item ) -> Acc ;
132143 // This has the same safety requirements as `Iterator::__iterator_get_unchecked`
133144 unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item
134145 where
@@ -228,6 +239,14 @@ where
228239 {
229240 unreachable ! ( "Always specialized" ) ;
230241 }
242+
243+ #[ inline]
244+ default fn fold < Acc , F > ( self , init : Acc , f : F ) -> Acc
245+ where
246+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
247+ {
248+ SpecFold :: spec_fold ( self , init, f)
249+ }
231250}
232251
233252#[ doc( hidden) ]
@@ -251,6 +270,24 @@ where
251270 // `Iterator::__iterator_get_unchecked`.
252271 unsafe { ( self . a . __iterator_get_unchecked ( idx) , self . b . __iterator_get_unchecked ( idx) ) }
253272 }
273+
274+ #[ inline]
275+ fn fold < Acc , F > ( mut self , init : Acc , mut f : F ) -> Acc
276+ where
277+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
278+ {
279+ let mut accum = init;
280+ let len = ZipImpl :: size_hint ( & self ) . 0 ;
281+ for 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.
285+ unsafe {
286+ accum = f ( accum, self . get_unchecked ( i) ) ;
287+ }
288+ }
289+ accum
290+ }
254291}
255292
256293#[ doc( hidden) ]
@@ -590,3 +627,56 @@ unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccess f
590627 unsafe { self . __iterator_get_unchecked ( index) }
591628 }
592629}
630+
631+ trait SpecFold : Iterator {
632+ fn spec_fold < B , F > ( self , init : B , f : F ) -> B
633+ where
634+ Self : Sized ,
635+ F : FnMut ( B , Self :: Item ) -> B ;
636+ }
637+
638+ impl < A : Iterator , B : Iterator > SpecFold for Zip < A , B > {
639+ // Adapted from default impl from the Iterator trait
640+ #[ inline]
641+ default fn spec_fold < Acc , F > ( mut self , init : Acc , mut f : F ) -> Acc
642+ where
643+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
644+ {
645+ let mut accum = init;
646+ while let Some ( x) = ZipImpl :: next ( & mut self ) {
647+ accum = f ( accum, x) ;
648+ }
649+ accum
650+ }
651+ }
652+
653+ impl < A : TrustedLen , B : TrustedLen > SpecFold for Zip < A , B > {
654+ #[ inline]
655+ fn spec_fold < Acc , F > ( mut self , init : Acc , mut f : F ) -> Acc
656+ where
657+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
658+ {
659+ let mut accum = init;
660+ loop {
661+ let ( upper, more) = if let Some ( upper) = ZipImpl :: size_hint ( & self ) . 1 {
662+ ( upper, false )
663+ } else {
664+ // Per TrustedLen contract a None upper bound means more than usize::MAX items
665+ ( usize:: MAX , true )
666+ } ;
667+
668+ for _ in 0 ..upper {
669+ let pair =
670+ // SAFETY: TrustedLen guarantees that at least `upper` many items are available
671+ // therefore we know they can't be None
672+ unsafe { ( self . a . next ( ) . unwrap_unchecked ( ) , self . b . next ( ) . unwrap_unchecked ( ) ) } ;
673+ accum = f ( accum, pair) ;
674+ }
675+
676+ if !more {
677+ break ;
678+ }
679+ }
680+ accum
681+ }
682+ }
0 commit comments