@@ -13,10 +13,6 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
1313pub struct Zip < A , B > {
1414 a : A ,
1515 b : B ,
16- // index, len and a_len are only used by the specialized version of zip
17- index : usize ,
18- len : usize ,
19- a_len : usize ,
2016}
2117impl < A : Iterator , B : Iterator > Zip < A , B > {
2218 pub ( in crate :: iter) fn new ( a : A , b : B ) -> Zip < A , B > {
@@ -88,14 +84,21 @@ where
8884 }
8985
9086 #[ inline]
91- #[ doc( hidden) ]
92- unsafe fn __iterator_get_unchecked ( & mut self , idx : usize ) -> Self :: Item
93- where
94- Self : TrustedRandomAccessNoCoerce ,
95- {
96- // SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
97- // requirements as `Iterator::__iterator_get_unchecked`.
98- unsafe { ZipImpl :: get_unchecked ( self , idx) }
87+ fn advance_by ( & mut self , n : usize ) -> Result < ( ) , usize > {
88+ let ( ( lower_a, _) , ( lower_b, _) ) = ( self . a . size_hint ( ) , self . b . size_hint ( ) ) ;
89+ let lower = n. min ( lower_a) . min ( lower_b) ;
90+ let batched = match ( self . b . advance_by ( lower) , self . a . advance_by ( lower) ) {
91+ ( Ok ( ( ) ) , Ok ( ( ) ) ) => lower,
92+ _ => panic ! ( "size_hint contract violation" ) ,
93+ } ;
94+
95+ for i in batched..n {
96+ if let ( _, None ) | ( None , _) = ( self . b . next ( ) , self . a . next ( ) ) {
97+ return Err ( i) ;
98+ }
99+ }
100+
101+ Ok ( ( ) )
99102 }
100103}
101104
@@ -123,30 +126,20 @@ trait ZipImpl<A, B> {
123126 where
124127 A : DoubleEndedIterator + ExactSizeIterator ,
125128 B : DoubleEndedIterator + ExactSizeIterator ;
126- // This has the same safety requirements as `Iterator::__iterator_get_unchecked`
127- unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item
128- where
129- Self : Iterator + TrustedRandomAccessNoCoerce ;
130129}
131130
132131// Work around limitations of specialization, requiring `default` impls to be repeated
133132// in intermediary impls.
134133macro_rules! zip_impl_general_defaults {
135134 ( ) => {
136135 default fn new( a: A , b: B ) -> Self {
137- Zip {
138- a,
139- b,
140- index: 0 , // unused
141- len: 0 , // unused
142- a_len: 0 , // unused
143- }
136+ Zip { a, b }
144137 }
145138
146139 #[ inline]
147140 default fn next( & mut self ) -> Option <( A :: Item , B :: Item ) > {
148- let x = self . a. next( ) ?;
149141 let y = self . b. next( ) ?;
142+ let x = self . a. next( ) ?;
150143 Some ( ( x, y) )
151144 }
152145
@@ -179,8 +172,8 @@ macro_rules! zip_impl_general_defaults {
179172 }
180173 }
181174 }
182- match ( self . a . next_back( ) , self . b . next_back( ) ) {
183- ( Some ( x ) , Some ( y ) ) => Some ( ( x, y) ) ,
175+ match ( self . b . next_back( ) , self . a . next_back( ) ) {
176+ ( Some ( y ) , Some ( x ) ) => Some ( ( x, y) ) ,
184177 ( None , None ) => None ,
185178 _ => unreachable!( ) ,
186179 }
@@ -215,157 +208,6 @@ where
215208
216209 ( lower, upper)
217210 }
218-
219- default unsafe fn get_unchecked ( & mut self , _idx : usize ) -> <Self as Iterator >:: Item
220- where
221- Self : TrustedRandomAccessNoCoerce ,
222- {
223- unreachable ! ( "Always specialized" ) ;
224- }
225- }
226-
227- #[ doc( hidden) ]
228- impl < A , B > ZipImpl < A , B > for Zip < A , B >
229- where
230- A : TrustedRandomAccessNoCoerce + Iterator ,
231- B : TrustedRandomAccessNoCoerce + Iterator ,
232- {
233- zip_impl_general_defaults ! { }
234-
235- #[ inline]
236- default fn size_hint ( & self ) -> ( usize , Option < usize > ) {
237- let size = cmp:: min ( self . a . size ( ) , self . b . size ( ) ) ;
238- ( size, Some ( size) )
239- }
240-
241- #[ inline]
242- unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item {
243- let idx = self . index + idx;
244- // SAFETY: the caller must uphold the contract for
245- // `Iterator::__iterator_get_unchecked`.
246- unsafe { ( self . a . __iterator_get_unchecked ( idx) , self . b . __iterator_get_unchecked ( idx) ) }
247- }
248- }
249-
250- #[ doc( hidden) ]
251- impl < A , B > ZipImpl < A , B > for Zip < A , B >
252- where
253- A : TrustedRandomAccess + Iterator ,
254- B : TrustedRandomAccess + Iterator ,
255- {
256- fn new ( a : A , b : B ) -> Self {
257- let a_len = a. size ( ) ;
258- let len = cmp:: min ( a_len, b. size ( ) ) ;
259- Zip { a, b, index : 0 , len, a_len }
260- }
261-
262- #[ inline]
263- fn next ( & mut self ) -> Option < ( A :: Item , B :: Item ) > {
264- if self . index < self . len {
265- let i = self . index ;
266- // since get_unchecked executes code which can panic we increment the counters beforehand
267- // so that the same index won't be accessed twice, as required by TrustedRandomAccess
268- self . index += 1 ;
269- // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
270- unsafe {
271- Some ( ( self . a . __iterator_get_unchecked ( i) , self . b . __iterator_get_unchecked ( i) ) )
272- }
273- } else if A :: MAY_HAVE_SIDE_EFFECT && self . index < self . a_len {
274- let i = self . index ;
275- // as above, increment before executing code that may panic
276- self . index += 1 ;
277- self . len += 1 ;
278- // match the base implementation's potential side effects
279- // SAFETY: we just checked that `i` < `self.a.len()`
280- unsafe {
281- self . a . __iterator_get_unchecked ( i) ;
282- }
283- None
284- } else {
285- None
286- }
287- }
288-
289- #[ inline]
290- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
291- let len = self . len - self . index ;
292- ( len, Some ( len) )
293- }
294-
295- #[ inline]
296- fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
297- let delta = cmp:: min ( n, self . len - self . index ) ;
298- let end = self . index + delta;
299- while self . index < end {
300- let i = self . index ;
301- // since get_unchecked executes code which can panic we increment the counters beforehand
302- // so that the same index won't be accessed twice, as required by TrustedRandomAccess
303- self . index += 1 ;
304- if A :: MAY_HAVE_SIDE_EFFECT {
305- // SAFETY: the usage of `cmp::min` to calculate `delta`
306- // ensures that `end` is smaller than or equal to `self.len`,
307- // so `i` is also smaller than `self.len`.
308- unsafe {
309- self . a . __iterator_get_unchecked ( i) ;
310- }
311- }
312- if B :: MAY_HAVE_SIDE_EFFECT {
313- // SAFETY: same as above.
314- unsafe {
315- self . b . __iterator_get_unchecked ( i) ;
316- }
317- }
318- }
319-
320- self . super_nth ( n - delta)
321- }
322-
323- #[ inline]
324- fn next_back ( & mut self ) -> Option < ( A :: Item , B :: Item ) >
325- where
326- A : DoubleEndedIterator + ExactSizeIterator ,
327- B : DoubleEndedIterator + ExactSizeIterator ,
328- {
329- if A :: MAY_HAVE_SIDE_EFFECT || B :: MAY_HAVE_SIDE_EFFECT {
330- let sz_a = self . a . size ( ) ;
331- let sz_b = self . b . size ( ) ;
332- // Adjust a, b to equal length, make sure that only the first call
333- // of `next_back` does this, otherwise we will break the restriction
334- // on calls to `self.next_back()` after calling `get_unchecked()`.
335- if sz_a != sz_b {
336- let sz_a = self . a . size ( ) ;
337- if A :: MAY_HAVE_SIDE_EFFECT && sz_a > self . len {
338- for _ in 0 ..sz_a - self . len {
339- // since next_back() may panic we increment the counters beforehand
340- // to keep Zip's state in sync with the underlying iterator source
341- self . a_len -= 1 ;
342- self . a . next_back ( ) ;
343- }
344- debug_assert_eq ! ( self . a_len, self . len) ;
345- }
346- let sz_b = self . b . size ( ) ;
347- if B :: MAY_HAVE_SIDE_EFFECT && sz_b > self . len {
348- for _ in 0 ..sz_b - self . len {
349- self . b . next_back ( ) ;
350- }
351- }
352- }
353- }
354- if self . index < self . len {
355- // since get_unchecked executes code which can panic we increment the counters beforehand
356- // so that the same index won't be accessed twice, as required by TrustedRandomAccess
357- self . len -= 1 ;
358- self . a_len -= 1 ;
359- let i = self . len ;
360- // SAFETY: `i` is smaller than the previous value of `self.len`,
361- // which is also smaller than or equal to `self.a.len()` and `self.b.len()`
362- unsafe {
363- Some ( ( self . a . __iterator_get_unchecked ( i) , self . b . __iterator_get_unchecked ( i) ) )
364- }
365- } else {
366- None
367- }
368- }
369211}
370212
371213#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -376,25 +218,6 @@ where
376218{
377219}
378220
379- #[ doc( hidden) ]
380- #[ unstable( feature = "trusted_random_access" , issue = "none" ) ]
381- unsafe impl < A , B > TrustedRandomAccess for Zip < A , B >
382- where
383- A : TrustedRandomAccess ,
384- B : TrustedRandomAccess ,
385- {
386- }
387-
388- #[ doc( hidden) ]
389- #[ unstable( feature = "trusted_random_access" , issue = "none" ) ]
390- unsafe impl < A , B > TrustedRandomAccessNoCoerce for Zip < A , B >
391- where
392- A : TrustedRandomAccessNoCoerce ,
393- B : TrustedRandomAccessNoCoerce ,
394- {
395- const MAY_HAVE_SIDE_EFFECT : bool = A :: MAY_HAVE_SIDE_EFFECT || B :: MAY_HAVE_SIDE_EFFECT ;
396- }
397-
398221#[ stable( feature = "fused" , since = "1.26.0" ) ]
399222impl < A , B > FusedIterator for Zip < A , B >
400223where
@@ -448,16 +271,6 @@ impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
448271 }
449272}
450273
451- impl < A : Debug + TrustedRandomAccessNoCoerce , B : Debug + TrustedRandomAccessNoCoerce > ZipFmt < A , B >
452- for Zip < A , B >
453- {
454- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
455- // It's *not safe* to call fmt on the contained iterators, since once
456- // we start iterating they're in strange, potentially unsafe, states.
457- f. debug_struct ( "Zip" ) . finish ( )
458- }
459- }
460-
461274/// An iterator whose items are random-accessible efficiently
462275///
463276/// # Safety
0 commit comments