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