@@ -184,8 +184,25 @@ pub trait Step: Clone + PartialOrd + Sized {
184184 }
185185}
186186
187- // These are still macro-generated because the integer literals resolve to different types.
188- macro_rules! step_identical_methods {
187+ // Separate impls for signed ranges because the distance within a signed range can be larger
188+ // than the signed::MAX value. THerefore `as` casting to the signed type would be incorrect.
189+ macro_rules! step_signed_methods {
190+ ( $unsigned: ty) => {
191+ #[ inline]
192+ unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
193+ // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
194+ unsafe { start. checked_add_unsigned( n as $unsigned) . unwrap_unchecked( ) }
195+ }
196+
197+ #[ inline]
198+ unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
199+ // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
200+ unsafe { start. checked_sub_unsigned( n as $unsigned) . unwrap_unchecked( ) }
201+ }
202+ } ;
203+ }
204+
205+ macro_rules! step_unsigned_methods {
189206 ( ) => {
190207 #[ inline]
191208 unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
@@ -198,7 +215,12 @@ macro_rules! step_identical_methods {
198215 // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
199216 unsafe { start. unchecked_sub( n as Self ) }
200217 }
218+ } ;
219+ }
201220
221+ // These are still macro-generated because the integer literals resolve to different types.
222+ macro_rules! step_identical_methods {
223+ ( ) => {
202224 #[ inline]
203225 #[ allow( arithmetic_overflow) ]
204226 #[ rustc_inherit_overflow_checks]
@@ -239,6 +261,7 @@ macro_rules! step_integer_impls {
239261 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
240262 impl Step for $u_narrower {
241263 step_identical_methods!( ) ;
264+ step_unsigned_methods!( ) ;
242265
243266 #[ inline]
244267 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -271,6 +294,7 @@ macro_rules! step_integer_impls {
271294 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
272295 impl Step for $i_narrower {
273296 step_identical_methods!( ) ;
297+ step_signed_methods!( $u_narrower) ;
274298
275299 #[ inline]
276300 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -335,6 +359,7 @@ macro_rules! step_integer_impls {
335359 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
336360 impl Step for $u_wider {
337361 step_identical_methods!( ) ;
362+ step_unsigned_methods!( ) ;
338363
339364 #[ inline]
340365 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -360,6 +385,7 @@ macro_rules! step_integer_impls {
360385 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
361386 impl Step for $i_wider {
362387 step_identical_methods!( ) ;
388+ step_signed_methods!( $u_wider) ;
363389
364390 #[ inline]
365391 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
0 commit comments