9191 #[ doc( hidden) ]
9292 unsafe fn __iterator_get_unchecked ( & mut self , idx : usize ) -> Self :: Item
9393 where
94- Self : TrustedRandomAccess ,
94+ Self : TrustedRandomAccessNoCoerce ,
9595 {
9696 // SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
9797 // requirements as `Iterator::__iterator_get_unchecked`.
@@ -126,7 +126,66 @@ trait ZipImpl<A, B> {
126126 // This has the same safety requirements as `Iterator::__iterator_get_unchecked`
127127 unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item
128128 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+ } ;
130189}
131190
132191// General Zip impl
@@ -137,54 +196,8 @@ where
137196 B : Iterator ,
138197{
139198 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- }
156199
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 ! { }
188201
189202 #[ inline]
190203 default fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -205,12 +218,35 @@ where
205218
206219 default unsafe fn get_unchecked ( & mut self , _idx : usize ) -> <Self as Iterator >:: Item
207220 where
208- Self : TrustedRandomAccess ,
221+ Self : TrustedRandomAccessNoCoerce ,
209222 {
210223 unreachable ! ( "Always specialized" ) ;
211224 }
212225}
213226
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+
214250#[ doc( hidden) ]
215251impl < A , B > ZipImpl < A , B > for Zip < A , B >
216252where
@@ -330,14 +366,6 @@ where
330366 None
331367 }
332368 }
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- }
341369}
342370
343371#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -426,7 +454,9 @@ impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
426454 }
427455}
428456
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+ {
430460 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
431461 // It's *not safe* to call fmt on the contained iterators, since once
432462 // we start iterating they're in strange, potentially unsafe, states.
@@ -448,6 +478,9 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
448478/// for bounds that come from the respective struct/enum definition itself, or bounds involving
449479/// traits that themselves come with a guarantee similar to this one.
450480///
481+ /// If `Self: ExactSizeIterator` then `self.len()` must always produce results consistent
482+ /// with `self.size()`.
483+ ///
451484/// If `Self: Iterator`, then `<Self as Iterator>::__iterator_get_unchecked(&mut self, idx)`
452485/// must be safe to call provided the following conditions are met.
453486///
@@ -463,6 +496,7 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
463496/// * `std::clone::Clone::clone`
464497/// * `std::iter::Iterator::size_hint`
465498/// * `std::iter::DoubleEndedIterator::next_back`
499+ /// * `std::iter::ExactSizeIterator::len`
466500/// * `std::iter::Iterator::__iterator_get_unchecked`
467501/// * `std::iter::TrustedRandomAccessNoCoerce::size`
468502/// 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 {
532566 }
533567}
534568
535- unsafe impl < I : Iterator + TrustedRandomAccess > SpecTrustedRandomAccess for I {
569+ unsafe impl < I : Iterator + TrustedRandomAccessNoCoerce > SpecTrustedRandomAccess for I {
536570 unsafe fn try_get_unchecked ( & mut self , index : usize ) -> Self :: Item {
537571 // SAFETY: the caller must uphold the contract for
538572 // `Iterator::__iterator_get_unchecked`.
0 commit comments