91
91
#[ doc( hidden) ]
92
92
unsafe fn __iterator_get_unchecked ( & mut self , idx : usize ) -> Self :: Item
93
93
where
94
- Self : TrustedRandomAccess ,
94
+ Self : TrustedRandomAccessNoCoerce ,
95
95
{
96
96
// SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
97
97
// requirements as `Iterator::__iterator_get_unchecked`.
@@ -126,7 +126,66 @@ trait ZipImpl<A, B> {
126
126
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
127
127
unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item
128
128
where
129
- Self : Iterator + TrustedRandomAccess ;
129
+ Self : Iterator + TrustedRandomAccessNoCoerce ;
130
+ }
131
+
132
+ // Work around limitations of specialization, requiring `default` impls to be repeated
133
+ // in intermediary impls.
134
+ macro_rules! zip_impl_general_defaults {
135
+ ( ) => {
136
+ 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
+ }
144
+ }
145
+
146
+ #[ inline]
147
+ default fn next( & mut self ) -> Option <( A :: Item , B :: Item ) > {
148
+ let x = self . a. next( ) ?;
149
+ let y = self . b. next( ) ?;
150
+ Some ( ( x, y) )
151
+ }
152
+
153
+ #[ inline]
154
+ default fn nth( & mut self , n: usize ) -> Option <Self :: Item > {
155
+ self . super_nth( n)
156
+ }
157
+
158
+ #[ inline]
159
+ default fn next_back( & mut self ) -> Option <( A :: Item , B :: Item ) >
160
+ where
161
+ A : DoubleEndedIterator + ExactSizeIterator ,
162
+ B : DoubleEndedIterator + ExactSizeIterator ,
163
+ {
164
+ // The function body below only uses `self.a/b.len()` and `self.a/b.next_back()`
165
+ // and doesn’t call `next_back` too often, so this implementation is safe in
166
+ // the `TrustedRandomAccessNoCoerce` specialization
167
+
168
+ let a_sz = self . a. len( ) ;
169
+ let b_sz = self . b. len( ) ;
170
+ if a_sz != b_sz {
171
+ // Adjust a, b to equal length
172
+ if a_sz > b_sz {
173
+ for _ in 0 ..a_sz - b_sz {
174
+ self . a. next_back( ) ;
175
+ }
176
+ } else {
177
+ for _ in 0 ..b_sz - a_sz {
178
+ self . b. next_back( ) ;
179
+ }
180
+ }
181
+ }
182
+ match ( self . a. next_back( ) , self . b. next_back( ) ) {
183
+ ( Some ( x) , Some ( y) ) => Some ( ( x, y) ) ,
184
+ ( None , None ) => None ,
185
+ _ => unreachable!( ) ,
186
+ }
187
+ }
188
+ } ;
130
189
}
131
190
132
191
// General Zip impl
@@ -137,54 +196,8 @@ where
137
196
B : Iterator ,
138
197
{
139
198
type Item = ( A :: Item , B :: Item ) ;
140
- default fn new ( a : A , b : B ) -> Self {
141
- Zip {
142
- a,
143
- b,
144
- index : 0 , // unused
145
- len : 0 , // unused
146
- a_len : 0 , // unused
147
- }
148
- }
149
-
150
- #[ inline]
151
- default fn next ( & mut self ) -> Option < ( A :: Item , B :: Item ) > {
152
- let x = self . a . next ( ) ?;
153
- let y = self . b . next ( ) ?;
154
- Some ( ( x, y) )
155
- }
156
199
157
- #[ inline]
158
- default fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
159
- self . super_nth ( n)
160
- }
161
-
162
- #[ inline]
163
- default fn next_back ( & mut self ) -> Option < ( A :: Item , B :: Item ) >
164
- where
165
- A : DoubleEndedIterator + ExactSizeIterator ,
166
- B : DoubleEndedIterator + ExactSizeIterator ,
167
- {
168
- let a_sz = self . a . len ( ) ;
169
- let b_sz = self . b . len ( ) ;
170
- if a_sz != b_sz {
171
- // Adjust a, b to equal length
172
- if a_sz > b_sz {
173
- for _ in 0 ..a_sz - b_sz {
174
- self . a . next_back ( ) ;
175
- }
176
- } else {
177
- for _ in 0 ..b_sz - a_sz {
178
- self . b . next_back ( ) ;
179
- }
180
- }
181
- }
182
- match ( self . a . next_back ( ) , self . b . next_back ( ) ) {
183
- ( Some ( x) , Some ( y) ) => Some ( ( x, y) ) ,
184
- ( None , None ) => None ,
185
- _ => unreachable ! ( ) ,
186
- }
187
- }
200
+ zip_impl_general_defaults ! { }
188
201
189
202
#[ inline]
190
203
default fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -205,12 +218,35 @@ where
205
218
206
219
default unsafe fn get_unchecked ( & mut self , _idx : usize ) -> <Self as Iterator >:: Item
207
220
where
208
- Self : TrustedRandomAccess ,
221
+ Self : TrustedRandomAccessNoCoerce ,
209
222
{
210
223
unreachable ! ( "Always specialized" ) ;
211
224
}
212
225
}
213
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
+
214
250
#[ doc( hidden) ]
215
251
impl < A , B > ZipImpl < A , B > for Zip < A , B >
216
252
where
@@ -330,14 +366,6 @@ where
330
366
None
331
367
}
332
368
}
333
-
334
- #[ inline]
335
- unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item {
336
- let idx = self . index + idx;
337
- // SAFETY: the caller must uphold the contract for
338
- // `Iterator::__iterator_get_unchecked`.
339
- unsafe { ( self . a . __iterator_get_unchecked ( idx) , self . b . __iterator_get_unchecked ( idx) ) }
340
- }
341
369
}
342
370
343
371
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -426,7 +454,9 @@ impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
426
454
}
427
455
}
428
456
429
- impl < A : Debug + TrustedRandomAccess , B : Debug + TrustedRandomAccess > ZipFmt < A , B > for Zip < A , B > {
457
+ impl < A : Debug + TrustedRandomAccessNoCoerce , B : Debug + TrustedRandomAccessNoCoerce > ZipFmt < A , B >
458
+ for Zip < A , B >
459
+ {
430
460
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
431
461
// It's *not safe* to call fmt on the contained iterators, since once
432
462
// we start iterating they're in strange, potentially unsafe, states.
@@ -448,6 +478,9 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
448
478
/// for bounds that come from the respective struct/enum definition itself, or bounds involving
449
479
/// traits that themselves come with a guarantee similar to this one.
450
480
///
481
+ /// If `Self: ExactSizeIterator` then `self.len()` must always produce results consistent
482
+ /// with `self.size()`.
483
+ ///
451
484
/// If `Self: Iterator`, then `<Self as Iterator>::__iterator_get_unchecked(&mut self, idx)`
452
485
/// must be safe to call provided the following conditions are met.
453
486
///
@@ -463,6 +496,7 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
463
496
/// * `std::clone::Clone::clone`
464
497
/// * `std::iter::Iterator::size_hint`
465
498
/// * `std::iter::DoubleEndedIterator::next_back`
499
+ /// * `std::iter::ExactSizeIterator::len`
466
500
/// * `std::iter::Iterator::__iterator_get_unchecked`
467
501
/// * `std::iter::TrustedRandomAccessNoCoerce::size`
468
502
/// 5. If `T` is a subtype of `Self`, then `self` is allowed to be coerced
@@ -532,7 +566,7 @@ unsafe impl<I: Iterator> SpecTrustedRandomAccess for I {
532
566
}
533
567
}
534
568
535
- unsafe impl < I : Iterator + TrustedRandomAccess > SpecTrustedRandomAccess for I {
569
+ unsafe impl < I : Iterator + TrustedRandomAccessNoCoerce > SpecTrustedRandomAccess for I {
536
570
unsafe fn try_get_unchecked ( & mut self , index : usize ) -> Self :: Item {
537
571
// SAFETY: the caller must uphold the contract for
538
572
// `Iterator::__iterator_get_unchecked`.
0 commit comments