@@ -2,6 +2,7 @@ use crate::intrinsics;
22use crate :: iter:: { TrustedLen , TrustedRandomAccess , from_fn} ;
33use crate :: num:: NonZero ;
44use crate :: ops:: { Range , Try } ;
5+ use crate :: range:: RangeIter ;
56
67/// An iterator for stepping iterators by a custom amount.
78///
@@ -418,37 +419,71 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
418419/// and we must consistently specialize backwards and forwards iteration
419420/// that makes the situation complicated enough that it's not covered
420421/// for now.
422+ ///
423+ /// After `SpecRangeSetup::setup`, both `Range<T>` and its new-range wrapper
424+ /// `RangeIter<T>` carry the cursor and countdown in the same underlying legacy
425+ /// `Range`. This accessor exposes that shared range so one specialization can
426+ /// serve both: it is an identity for `Range<T>` and unwraps the newtype for
427+ /// `RangeIter<T>`, so it compiles away.
428+ trait AsLegacyRange < T > {
429+ fn as_legacy_range ( & self ) -> & Range < T > ;
430+ fn as_legacy_range_mut ( & mut self ) -> & mut Range < T > ;
431+ }
432+
433+ impl < T > AsLegacyRange < T > for Range < T > {
434+ #[ inline]
435+ fn as_legacy_range ( & self ) -> & Range < T > {
436+ self
437+ }
438+ #[ inline]
439+ fn as_legacy_range_mut ( & mut self ) -> & mut Range < T > {
440+ self
441+ }
442+ }
443+
444+ impl < T > AsLegacyRange < T > for RangeIter < T > {
445+ #[ inline]
446+ fn as_legacy_range ( & self ) -> & Range < T > {
447+ & self . 0
448+ }
449+ #[ inline]
450+ fn as_legacy_range_mut ( & mut self ) -> & mut Range < T > {
451+ & mut self . 0
452+ }
453+ }
454+
421455macro_rules! spec_int_ranges {
422- ( $( $t: ty) * ) => ( $(
456+ ( $ctor : ident ; $ ( $t: ty) * ) => ( $(
423457
424458 const _: ( ) = assert!( usize :: BITS >= <$t>:: BITS ) ;
425459
426- impl SpecRangeSetup <Range <$t>> for Range <$t> {
460+ impl SpecRangeSetup <$ctor <$t>> for $ctor <$t> {
427461 #[ inline]
428- fn setup( mut r: Range <$t>, step: usize ) -> Range <$t> {
462+ fn setup( mut r: $ctor <$t>, step: usize ) -> $ctor <$t> {
429463 let inner_len = r. size_hint( ) . 0 ;
430464 // If step exceeds $t::MAX, then the count will be at most 1 and
431465 // thus always fit into $t.
432466 let yield_count = inner_len. div_ceil( step) ;
433467 // Turn the range end into an iteration counter
434- r. end = yield_count as $t;
468+ r. as_legacy_range_mut ( ) . end = yield_count as $t;
435469 r
436470 }
437471 }
438472
439- unsafe impl StepByImpl <Range <$t>> for StepBy <Range <$t>> {
473+ unsafe impl StepByImpl <$ctor <$t>> for StepBy <$ctor <$t>> {
440474 #[ inline]
441475 fn spec_next( & mut self ) -> Option <$t> {
442476 // if a step size larger than the type has been specified fall back to
443477 // t::MAX, in which case remaining will be at most 1.
444478 let step = <$t>:: try_from( self . original_step( ) . get( ) ) . unwrap_or( <$t>:: MAX ) ;
445- let remaining = self . iter. end;
479+ let r = self . iter. as_legacy_range_mut( ) ;
480+ let remaining = r. end;
446481 if remaining > 0 {
447- let val = self . iter . start;
482+ let val = r . start;
448483 // this can only overflow during the last step, after which the value
449484 // will not be used
450- self . iter . start = val. wrapping_add( step) ;
451- self . iter . end = remaining - 1 ;
485+ r . start = val. wrapping_add( step) ;
486+ r . end = remaining - 1 ;
452487 Some ( val)
453488 } else {
454489 None
@@ -457,7 +492,7 @@ macro_rules! spec_int_ranges {
457492
458493 #[ inline]
459494 fn spec_size_hint( & self ) -> ( usize , Option <usize >) {
460- let remaining = self . iter. end as usize ;
495+ let remaining = self . iter. as_legacy_range ( ) . end as usize ;
461496 ( remaining, Some ( remaining) )
462497 }
463498
@@ -491,9 +526,10 @@ macro_rules! spec_int_ranges {
491526 // if a step size larger than the type has been specified fall back to
492527 // t::MAX, in which case remaining will be at most 1.
493528 let step = <$t>:: try_from( self . original_step( ) . get( ) ) . unwrap_or( <$t>:: MAX ) ;
494- let remaining = self . iter. end;
529+ let r = self . iter. as_legacy_range( ) ;
530+ let remaining = r. end;
495531 let mut acc = init;
496- let mut val = self . iter . start;
532+ let mut val = r . start;
497533 for _ in 0 ..remaining {
498534 acc = f( acc, val) ;
499535 // this can only overflow during the last step, after which the value
@@ -507,18 +543,19 @@ macro_rules! spec_int_ranges {
507543}
508544
509545macro_rules! spec_int_ranges_r {
510- ( $( $t: ty) * ) => ( $(
546+ ( $ctor : ident ; $ ( $t: ty) * ) => ( $(
511547 const _: ( ) = assert!( usize :: BITS >= <$t>:: BITS ) ;
512548
513- unsafe impl StepByBackImpl <Range <$t>> for StepBy <Range <$t>> {
549+ unsafe impl StepByBackImpl <$ctor <$t>> for StepBy <$ctor <$t>> {
514550
515551 #[ inline]
516552 fn spec_next_back( & mut self ) -> Option <Self :: Item > {
517553 let step = self . original_step( ) . get( ) as $t;
518- let remaining = self . iter. end;
554+ let r = self . iter. as_legacy_range_mut( ) ;
555+ let remaining = r. end;
519556 if remaining > 0 {
520- let start = self . iter . start;
521- self . iter . end = remaining - 1 ;
557+ let start = r . start;
558+ r . end = remaining - 1 ;
522559 Some ( start + step * ( remaining - 1 ) )
523560 } else {
524561 None
@@ -564,18 +601,37 @@ macro_rules! spec_int_ranges_r {
564601 ) * )
565602}
566603
604+ // The same specialization covers `Range<{integer}>` and the new-range iterator
605+ // `RangeIter<{integer}>`, which wraps a `Range` (see `AsLegacyRange`).
606+ //
607+ // The backward (`_r`) specialization requires `ExactSizeIterator`. `RangeIter`
608+ // implements it only for `usize`/`u8`/`u16` (see `range_exact_iter_impl!` in
609+ // `range::iter`), narrower than `Range`, so `RangeIter`'s backward set omits
610+ // `u32` even where `Range` includes it; `Range<u64>` is likewise omitted on
611+ // 64-bit since its length can exceed `usize`.
567612#[ cfg( target_pointer_width = "64" ) ]
568- spec_int_ranges ! ( u8 u16 u32 u64 usize ) ;
569- // DoubleEndedIterator requires ExactSizeIterator, which isn't implemented for Range<u64>
570- #[ cfg( target_pointer_width = "64" ) ]
571- spec_int_ranges_r ! ( u8 u16 u32 usize ) ;
613+ mod step_by_spec {
614+ use super :: * ;
615+ spec_int_ranges ! ( Range ; u8 u16 u32 u64 usize ) ;
616+ spec_int_ranges ! ( RangeIter ; u8 u16 u32 u64 usize ) ;
617+ spec_int_ranges_r ! ( Range ; u8 u16 u32 usize ) ;
618+ spec_int_ranges_r ! ( RangeIter ; u8 u16 usize ) ;
619+ }
572620
573621#[ cfg( target_pointer_width = "32" ) ]
574- spec_int_ranges ! ( u8 u16 u32 usize ) ;
575- #[ cfg( target_pointer_width = "32" ) ]
576- spec_int_ranges_r ! ( u8 u16 u32 usize ) ;
622+ mod step_by_spec {
623+ use super :: * ;
624+ spec_int_ranges ! ( Range ; u8 u16 u32 usize ) ;
625+ spec_int_ranges ! ( RangeIter ; u8 u16 u32 usize ) ;
626+ spec_int_ranges_r ! ( Range ; u8 u16 u32 usize ) ;
627+ spec_int_ranges_r ! ( RangeIter ; u8 u16 usize ) ;
628+ }
577629
578630#[ cfg( target_pointer_width = "16" ) ]
579- spec_int_ranges ! ( u8 u16 usize ) ;
580- #[ cfg( target_pointer_width = "16" ) ]
581- spec_int_ranges_r ! ( u8 u16 usize ) ;
631+ mod step_by_spec {
632+ use super :: * ;
633+ spec_int_ranges ! ( Range ; u8 u16 usize ) ;
634+ spec_int_ranges ! ( RangeIter ; u8 u16 usize ) ;
635+ spec_int_ranges_r ! ( Range ; u8 u16 usize ) ;
636+ spec_int_ranges_r ! ( RangeIter ; u8 u16 usize ) ;
637+ }
0 commit comments