@@ -22,7 +22,7 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
22
22
///
23
23
/// The *successor* operation moves towards values that compare greater.
24
24
/// The *predecessor* operation moves towards values that compare lesser.
25
- #[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
25
+ #[ unstable( feature = "step_trait" , issue = "42168" ) ]
26
26
pub trait Step : Clone + PartialOrd + Sized {
27
27
/// Returns the number of *successor* steps required to get from `start` to `end`.
28
28
///
@@ -52,15 +52,12 @@ pub trait Step: Clone + PartialOrd + Sized {
52
52
/// For any `a`, `n`, and `m`:
53
53
///
54
54
/// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))`
55
- ///
56
- /// For any `a`, `n`, and `m` where `n + m` does not overflow:
57
- ///
58
- /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, n + m)`
55
+ /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == try { Step::forward_checked(a, n.checked_add(m)) }`
59
56
///
60
57
/// For any `a` and `n`:
61
58
///
62
59
/// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))`
63
- /// * Corollary: `Step::forward_checked(& a, 0) == Some(a)`
60
+ /// * Corollary: `Step::forward_checked(a, 0) == Some(a)`
64
61
fn forward_checked ( start : Self , count : usize ) -> Option < Self > ;
65
62
66
63
/// Returns the value that would be obtained by taking the *successor*
@@ -106,6 +103,7 @@ pub trait Step: Clone + PartialOrd + Sized {
106
103
/// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)`
107
104
/// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`,
108
105
/// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`.
106
+ /// * Corollary: `Step::forward_unchecked(a, 0)` is always safe.
109
107
///
110
108
/// For any `a` and `n`, where no overflow occurs:
111
109
///
@@ -128,8 +126,8 @@ pub trait Step: Clone + PartialOrd + Sized {
128
126
///
129
127
/// For any `a` and `n`:
130
128
///
131
- /// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(& x, 1))`
132
- /// * Corollary: `Step::backward_checked(& a, 0) == Some(a)`
129
+ /// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(x, 1))`
130
+ /// * Corollary: `Step::backward_checked(a, 0) == Some(a)`
133
131
fn backward_checked ( start : Self , count : usize ) -> Option < Self > ;
134
132
135
133
/// Returns the value that would be obtained by taking the *predecessor*
@@ -175,6 +173,7 @@ pub trait Step: Clone + PartialOrd + Sized {
175
173
/// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)`
176
174
/// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`,
177
175
/// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`.
176
+ /// * Corollary: `Step::backward_unchecked(a, 0)` is always safe.
178
177
///
179
178
/// For any `a` and `n`, where no overflow occurs:
180
179
///
@@ -184,8 +183,25 @@ pub trait Step: Clone + PartialOrd + Sized {
184
183
}
185
184
}
186
185
187
- // These are still macro-generated because the integer literals resolve to different types.
188
- 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 {
189
205
( ) => {
190
206
#[ inline]
191
207
unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
@@ -198,7 +214,12 @@ macro_rules! step_identical_methods {
198
214
// SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
199
215
unsafe { start. unchecked_sub( n as Self ) }
200
216
}
217
+ } ;
218
+ }
201
219
220
+ // These are still macro-generated because the integer literals resolve to different types.
221
+ macro_rules! step_identical_methods {
222
+ ( ) => {
202
223
#[ inline]
203
224
#[ allow( arithmetic_overflow) ]
204
225
#[ rustc_inherit_overflow_checks]
@@ -239,6 +260,7 @@ macro_rules! step_integer_impls {
239
260
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
240
261
impl Step for $u_narrower {
241
262
step_identical_methods!( ) ;
263
+ step_unsigned_methods!( ) ;
242
264
243
265
#[ inline]
244
266
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -271,6 +293,7 @@ macro_rules! step_integer_impls {
271
293
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
272
294
impl Step for $i_narrower {
273
295
step_identical_methods!( ) ;
296
+ step_signed_methods!( $u_narrower) ;
274
297
275
298
#[ inline]
276
299
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -335,6 +358,7 @@ macro_rules! step_integer_impls {
335
358
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
336
359
impl Step for $u_wider {
337
360
step_identical_methods!( ) ;
361
+ step_unsigned_methods!( ) ;
338
362
339
363
#[ inline]
340
364
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
@@ -360,6 +384,7 @@ macro_rules! step_integer_impls {
360
384
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
361
385
impl Step for $i_wider {
362
386
step_identical_methods!( ) ;
387
+ step_signed_methods!( $u_wider) ;
363
388
364
389
#[ inline]
365
390
fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
0 commit comments