@@ -13,10 +13,6 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
13
13
pub struct Zip < A , B > {
14
14
a : A ,
15
15
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 ,
20
16
}
21
17
impl < A : Iterator , B : Iterator > Zip < A , B > {
22
18
pub ( in crate :: iter) fn new ( a : A , b : B ) -> Zip < A , B > {
@@ -88,14 +84,21 @@ where
88
84
}
89
85
90
86
#[ 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 ( ( ) )
99
102
}
100
103
}
101
104
@@ -123,30 +126,20 @@ trait ZipImpl<A, B> {
123
126
where
124
127
A : DoubleEndedIterator + ExactSizeIterator ,
125
128
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 ;
130
129
}
131
130
132
131
// Work around limitations of specialization, requiring `default` impls to be repeated
133
132
// in intermediary impls.
134
133
macro_rules! zip_impl_general_defaults {
135
134
( ) => {
136
135
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 }
144
137
}
145
138
146
139
#[ inline]
147
140
default fn next( & mut self ) -> Option <( A :: Item , B :: Item ) > {
148
- let x = self . a. next( ) ?;
149
141
let y = self . b. next( ) ?;
142
+ let x = self . a. next( ) ?;
150
143
Some ( ( x, y) )
151
144
}
152
145
@@ -179,8 +172,8 @@ macro_rules! zip_impl_general_defaults {
179
172
}
180
173
}
181
174
}
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) ) ,
184
177
( None , None ) => None ,
185
178
_ => unreachable!( ) ,
186
179
}
@@ -215,157 +208,6 @@ where
215
208
216
209
( lower, upper)
217
210
}
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
- }
369
211
}
370
212
371
213
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -376,25 +218,6 @@ where
376
218
{
377
219
}
378
220
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
-
398
221
#[ stable( feature = "fused" , since = "1.26.0" ) ]
399
222
impl < A , B > FusedIterator for Zip < A , B >
400
223
where
@@ -448,16 +271,6 @@ impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
448
271
}
449
272
}
450
273
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
-
461
274
/// An iterator whose items are random-accessible efficiently
462
275
///
463
276
/// # Safety
0 commit comments