@@ -183,8 +183,25 @@ pub trait Step: Clone + PartialOrd + Sized {
183
183
}
184
184
}
185
185
186
- // These are still macro-generated because the integer literals resolve to different types.
187
- macro_rules! step_identical_methods {
186
+ // Separate impls for signed ranges because the distance within a signed range can be larger
187
+ // than the signed::MAX value. Therefore `as` casting to the signed type would be incorrect.
188
+ macro_rules! step_signed_methods {
189
+ ( $unsigned: ty) => {
190
+ #[ inline]
191
+ unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
192
+ // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
193
+ unsafe { start. checked_add_unsigned( n as $unsigned) . unwrap_unchecked( ) }
194
+ }
195
+
196
+ #[ inline]
197
+ unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
198
+ // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
199
+ unsafe { start. checked_sub_unsigned( n as $unsigned) . unwrap_unchecked( ) }
200
+ }
201
+ } ;
202
+ }
203
+
204
+ macro_rules! step_unsigned_methods {
188
205
( ) => {
189
206
#[ inline]
190
207
unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
@@ -197,7 +214,12 @@ macro_rules! step_identical_methods {
197
214
// SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
198
215
unsafe { start. unchecked_sub( n as Self ) }
199
216
}
217
+ } ;
218
+ }
200
219
220
+ // These are still macro-generated because the integer literals resolve to different types.
221
+ macro_rules! step_identical_methods {
222
+ ( ) => {
201
223
#[ inline]
202
224
#[ allow( arithmetic_overflow) ]
203
225
#[ rustc_inherit_overflow_checks]
@@ -238,6 +260,7 @@ macro_rules! step_integer_impls {
238
260
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
239
261
impl Step for $u_narrower {
240
262
step_identical_methods!( ) ;
263
+ step_unsigned_methods!( ) ;
241
264
242
265
#[ inline]
243
266
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -270,6 +293,7 @@ macro_rules! step_integer_impls {
270
293
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
271
294
impl Step for $i_narrower {
272
295
step_identical_methods!( ) ;
296
+ step_signed_methods!( $u_narrower) ;
273
297
274
298
#[ inline]
275
299
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -334,6 +358,7 @@ macro_rules! step_integer_impls {
334
358
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
335
359
impl Step for $u_wider {
336
360
step_identical_methods!( ) ;
361
+ step_unsigned_methods!( ) ;
337
362
338
363
#[ inline]
339
364
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -359,6 +384,7 @@ macro_rules! step_integer_impls {
359
384
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
360
385
impl Step for $i_wider {
361
386
step_identical_methods!( ) ;
387
+ step_signed_methods!( $u_wider) ;
362
388
363
389
#[ inline]
364
390
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
0 commit comments