@@ -184,8 +184,25 @@ pub trait Step: Clone + PartialOrd + Sized {
184
184
}
185
185
}
186
186
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 {
189
206
( ) => {
190
207
#[ inline]
191
208
unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
@@ -198,7 +215,12 @@ macro_rules! step_identical_methods {
198
215
// SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
199
216
unsafe { start. unchecked_sub( n as Self ) }
200
217
}
218
+ } ;
219
+ }
201
220
221
+ // These are still macro-generated because the integer literals resolve to different types.
222
+ macro_rules! step_identical_methods {
223
+ ( ) => {
202
224
#[ inline]
203
225
#[ allow( arithmetic_overflow) ]
204
226
#[ rustc_inherit_overflow_checks]
@@ -239,6 +261,7 @@ macro_rules! step_integer_impls {
239
261
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
240
262
impl Step for $u_narrower {
241
263
step_identical_methods!( ) ;
264
+ step_unsigned_methods!( ) ;
242
265
243
266
#[ inline]
244
267
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -271,6 +294,7 @@ macro_rules! step_integer_impls {
271
294
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
272
295
impl Step for $i_narrower {
273
296
step_identical_methods!( ) ;
297
+ step_signed_methods!( $u_narrower) ;
274
298
275
299
#[ inline]
276
300
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -335,6 +359,7 @@ macro_rules! step_integer_impls {
335
359
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
336
360
impl Step for $u_wider {
337
361
step_identical_methods!( ) ;
362
+ step_unsigned_methods!( ) ;
338
363
339
364
#[ inline]
340
365
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -360,6 +385,7 @@ macro_rules! step_integer_impls {
360
385
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
361
386
impl Step for $i_wider {
362
387
step_identical_methods!( ) ;
388
+ step_signed_methods!( $u_wider) ;
363
389
364
390
#[ inline]
365
391
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
0 commit comments