@@ -15,6 +15,7 @@ macro_rules! unsafe_impl_trusted_step {
1515 ) * } ;
1616}
1717unsafe_impl_trusted_step ! [ AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize Ipv4Addr Ipv6Addr ] ;
18+ unsafe_impl_trusted_step ! [ NonZero <u8 > NonZero <u16 > NonZero <u32 > NonZero <u64 > NonZero <u128 > NonZero <usize >] ;
1819
1920/// Objects that have a notion of *successor* and *predecessor* operations.
2021///
@@ -255,10 +256,8 @@ macro_rules! step_identical_methods {
255256
256257macro_rules! step_integer_impls {
257258 {
258- narrower than or same width as usize :
259- $( [ $u_narrower: ident $i_narrower: ident ] ) , +;
260- wider than usize :
261- $( [ $u_wider: ident $i_wider: ident ] ) , +;
259+ [ $( [ $u_narrower: ident $i_narrower: ident ] ) , + ] <= usize <
260+ [ $( [ $u_wider: ident $i_wider: ident ] ) , + ]
262261 } => {
263262 $(
264263 #[ allow ( unreachable_patterns) ]
@@ -437,20 +436,138 @@ macro_rules! step_integer_impls {
437436
438437#[ cfg ( target_pointer_width = "64" ) ]
439438step_integer_impls! {
440- narrower than or same width as usize : [ u8 i8] , [ u16 i16] , [ u32 i32] , [ u64 i64] , [ usize isize] ;
441- wider than usize : [ u128 i128] ;
439+ [ [ u8 i8] , [ u16 i16] , [ u32 i32] , [ u64 i64] , [ usize isize] ] <= usize < [ [ u128 i128] ]
442440}
443441
444442#[ cfg ( target_pointer_width = "32" ) ]
445443step_integer_impls! {
446- narrower than or same width as usize : [ u8 i8 ] , [ u16 i16 ] , [ u32 i32 ] , [ usize isize ] ;
447- wider than usize : [ u64 i64 ] , [ u128 i128 ] ;
444+ [ [ u8 i8] , [ u16 i16] , [ u32 i32] , [ usize isize] ] <= usize < [ [ u64 i64] , [ u128 i128] ]
448445}
449446
450447#[ cfg ( target_pointer_width = "16" ) ]
451448step_integer_impls! {
452- narrower than or same width as usize : [ u8 i8 ] , [ u16 i16 ] , [ usize isize ] ;
453- wider than usize : [ u32 i32 ] , [ u64 i64 ] , [ u128 i128 ] ;
449+ [ [ u8 i8] , [ u16 i16] , [ usize isize] ] <= usize < [ [ u32 i32] , [ u64 i64] , [ u128 i128] ]
450+ }
451+
452+ // These are still macro-generated because the integer literals resolve to different types.
453+ macro_rules! step_nonzero_identical_methods {
454+ ( $int: ident) => {
455+ #[ inline]
456+ unsafe fn forward_unchecked( start: Self , n: usize) -> Self {
457+ // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
458+ unsafe { Self : : new_unchecked ( start. get ( ) . unchecked_add ( n as $int) ) }
459+ }
460+
461+ #[ inline]
462+ unsafe fn backward_unchecked( start: Self , n: usize) -> Self {
463+ // SAFETY: the caller has to guarantee that `start - n` doesn't overflow or hit zero.
464+ unsafe { Self : : new_unchecked ( start. get ( ) . unchecked_sub ( n as $int) ) }
465+ }
466+
467+ #[ inline]
468+ #[ allow ( arithmetic_overflow) ]
469+ #[ rustc_inherit_overflow_checks]
470+ fn forward( start: Self , n: usize) -> Self {
471+ // In debug builds, trigger a panic on overflow.
472+ // This should optimize completely out in release builds.
473+ if Self :: forward_checked ( start, n) . is_none ( ) {
474+ let _ = $int:: MAX + 1 ;
475+ }
476+ // Do saturating math (wrapping math causes UB if it wraps to Zero)
477+ start. saturating_add ( n as $int)
478+ }
479+
480+ #[ inline]
481+ #[ allow ( arithmetic_overflow) ]
482+ #[ rustc_inherit_overflow_checks]
483+ fn backward( start: Self , n: usize) -> Self {
484+ // In debug builds, trigger a panic on overflow.
485+ // This should optimize completely out in release builds.
486+ if Self :: backward_checked ( start, n) . is_none ( ) {
487+ let _ = $int:: MIN - 1 ;
488+ }
489+ // Do saturating math (wrapping math causes UB if it wraps to Zero)
490+ Self :: new ( start. get ( ) . saturating_sub ( n as $int) ) . unwrap_or ( Self :: MIN )
491+ }
492+
493+ #[ inline]
494+ fn steps_between ( start: & Self , end: & Self ) -> ( usize, Option <usize>) {
495+ if * start <= * end {
496+ #[ allow( irrefutable_let_patterns, reason = "happens on usize or narrower" ) ]
497+ if let Ok ( steps) = usize:: try_from ( end. get ( ) - start. get ( ) ) {
498+ ( steps, Some ( steps) )
499+ } else {
500+ ( usize:: MAX , None )
501+ }
502+ } else {
503+ ( 0 , None )
504+ }
505+ }
506+ } ;
507+ }
508+
509+ macro_rules! step_nonzero_impls {
510+ {
511+ [ $( $narrower: ident ) , +] <= usize < [ $( $wider: ident ) , +]
512+ } => {
513+ $(
514+ #[ allow ( unreachable_patterns) ]
515+ #[ unstable ( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
516+ impl Step for NonZero <$narrower> {
517+ step_nonzero_identical_methods ! ( $narrower) ;
518+
519+ #[ inline]
520+ fn forward_checked ( start : Self , n : usize ) -> Option < Self > {
521+ match $narrower:: try_from ( n) {
522+ Ok ( n) => start. checked_add ( n) ,
523+ Err ( _) => None , // if n is out of range, `unsigned_start + n` is too
524+ }
525+ }
526+
527+ #[ inline]
528+ fn backward_checked ( start : Self , n : usize ) -> Option < Self > {
529+ match $narrower:: try_from ( n) {
530+ // *_sub() is not implemented on NonZero<T>
531+ Ok ( n) => start. get ( ) . checked_sub ( n) . and_then ( Self :: new) ,
532+ Err ( _) => None , // if n is out of range, `unsigned_start - n` is too
533+ }
534+ }
535+ }
536+ ) +
537+
538+ $(
539+ #[ allow( unreachable_patterns) ]
540+ #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
541+ impl Step for NonZero <$wider> {
542+ step_nonzero_identical_methods ! ( $wider) ;
543+
544+ #[ inline]
545+ fn forward_checked ( start : Self , n : usize ) -> Option < Self > {
546+ start. checked_add ( n as $wider)
547+ }
548+
549+ #[ inline]
550+ fn backward_checked ( start : Self , n : usize ) -> Option < Self > {
551+ start. get ( ) . checked_sub ( n as $wider) . and_then ( Self :: new)
552+ }
553+ }
554+ ) +
555+ } ;
556+ }
557+
558+ #[ cfg ( target_pointer_width = "64" ) ]
559+ step_nonzero_impls! {
560+ [ u8 , u16 , u32 , u64 , usize ] <= usize < [ u128 ]
561+ }
562+
563+ #[ cfg( target_pointer_width = "32" ) ]
564+ step_nonzero_impls! {
565+ [ u8 , u16 , u32 , usize ] <= usize < [ u64 , u128 ]
566+ }
567+
568+ #[ cfg( target_pointer_width = "16" ) ]
569+ step_nonzero_impls! {
570+ [ u8 , u16 , usize ] <= usize < [ u32 , u64 , u128 ]
454571}
455572
456573#[ unstable( feature = "step_trait" , issue = "42168" ) ]
@@ -944,6 +1061,7 @@ impl<A: Step> Iterator for ops::Range<A> {
9441061range_exact_iter_impl! {
9451062 usize u8 u16
9461063 isize i8 i16
1064+ NonZero <usize > NonZero <u8 > NonZero <u16 >
9471065
9481066 // These are incorrect per the reasoning above,
9491067 // but removing them would be a breaking change as they were stabilized in Rust 1.0.0.
@@ -956,22 +1074,30 @@ range_exact_iter_impl! {
9561074unsafe_range_trusted_random_access_impl! {
9571075 usize u8 u16
9581076 isize i8 i16
1077+ NonZero <usize > NonZero <u8 > NonZero <u16 >
9591078}
9601079
9611080#[ cfg( target_pointer_width = "32" ) ]
9621081unsafe_range_trusted_random_access_impl! {
9631082 u32 i32
1083+ NonZero <u32 >
9641084}
9651085
9661086#[ cfg( target_pointer_width = "64" ) ]
9671087unsafe_range_trusted_random_access_impl! {
9681088 u32 i32
9691089 u64 i64
1090+ NonZero <u32 >
1091+ NonZero <u64 >
9701092}
9711093
9721094range_incl_exact_iter_impl! {
9731095 u8
9741096 i8
1097+ NonZero <u8 >
1098+ // Since RangeInclusive<NonZero<uN>> can only be 1..=uN::MAX the length of this range is always
1099+ // <= uN::MAX, so they are always valid ExactSizeIterator unlike the ranges that include zero.
1100+ NonZero <u16 > NonZero <usize >
9751101
9761102 // These are incorrect per the reasoning above,
9771103 // but removing them would be a breaking change as they were stabilized in Rust 1.26.0.
0 commit comments