@@ -184,8 +184,26 @@ 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+
188+ // Separate impls for signed ranges because the distance within a signed range can be larger
189+ // than the signed::MAX value. THerefore `as` casting to the signed type would be incorrect.
190+ macro_rules! step_signed_methods {
191+ ( $unsigned: ty) => {
192+ #[ inline]
193+ unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
194+ // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
195+ unsafe { start. checked_add_unsigned( n as $unsigned) . unwrap_unchecked( ) }
196+ }
197+
198+ #[ inline]
199+ unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
200+ // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
201+ unsafe { start. checked_sub_unsigned( n as $unsigned) . unwrap_unchecked( ) }
202+ }
203+ }
204+ }
205+
206+ macro_rules! step_unsigned_methods {
189207 ( ) => {
190208 #[ inline]
191209 unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
@@ -198,7 +216,12 @@ macro_rules! step_identical_methods {
198216 // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
199217 unsafe { start. unchecked_sub( n as Self ) }
200218 }
219+ }
220+ }
201221
222+ // These are still macro-generated because the integer literals resolve to different types.
223+ macro_rules! step_identical_methods {
224+ ( ) => {
202225 #[ inline]
203226 #[ allow( arithmetic_overflow) ]
204227 #[ rustc_inherit_overflow_checks]
@@ -239,6 +262,7 @@ macro_rules! step_integer_impls {
239262 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
240263 impl Step for $u_narrower {
241264 step_identical_methods!( ) ;
265+ step_unsigned_methods!( ) ;
242266
243267 #[ inline]
244268 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -271,6 +295,7 @@ macro_rules! step_integer_impls {
271295 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
272296 impl Step for $i_narrower {
273297 step_identical_methods!( ) ;
298+ step_signed_methods!( $u_narrower) ;
274299
275300 #[ inline]
276301 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -335,6 +360,7 @@ macro_rules! step_integer_impls {
335360 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
336361 impl Step for $u_wider {
337362 step_identical_methods!( ) ;
363+ step_unsigned_methods!( ) ;
338364
339365 #[ inline]
340366 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -360,6 +386,7 @@ macro_rules! step_integer_impls {
360386 #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
361387 impl Step for $i_wider {
362388 step_identical_methods!( ) ;
389+ step_signed_methods!( $u_wider) ;
363390
364391 #[ inline]
365392 fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
0 commit comments