@@ -22,23 +22,21 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
22
22
/// The *predecessor* operation moves towards values that compare lesser.
23
23
#[ unstable( feature = "step_trait" , issue = "42168" ) ]
24
24
pub trait Step : Clone + PartialOrd + Sized {
25
- /// Returns the number of *successor* steps required to get from `start` to `end`.
25
+ /// Returns the bounds on the number of *successor* steps required to get from `start` to `end`
26
+ /// like [`Iterator::size_hint()`][Iterator::size_hint()].
26
27
///
27
- /// Returns `None` if the number of steps would overflow `usize`
28
- /// (or is infinite, or if `end` would never be reached).
28
+ /// Returns `(usize::MAX, None)` if the number of steps would overflow `usize`, or is infinite.
29
29
///
30
30
/// # Invariants
31
31
///
32
32
/// For any `a`, `b`, and `n`:
33
33
///
34
- /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward_checked(&a, n) == Some(b)`
35
- /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&b, n) == Some(a)`
36
- /// * `steps_between(&a, &b) == Some(n)` only if `a <= b`
37
- /// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b`
38
- /// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
39
- /// this is the case when it would require more than `usize::MAX` steps to get to `b`
40
- /// * `steps_between(&a, &b) == None` if `a > b`
41
- fn steps_between ( start : & Self , end : & Self ) -> Option < usize > ;
34
+ /// * `steps_between(&a, &b) == (n, Some(n))` if and only if `Step::forward_checked(&a, n) == Some(b)`
35
+ /// * `steps_between(&a, &b) == (n, Some(n))` if and only if `Step::backward_checked(&b, n) == Some(a)`
36
+ /// * `steps_between(&a, &b) == (n, Some(n))` only if `a <= b`
37
+ /// * Corollary: `steps_between(&a, &b) == (0, Some(0))` if and only if `a == b`
38
+ /// * `steps_between(&a, &b) == (0, None)` if `a > b`
39
+ fn steps_between ( start : & Self , end : & Self ) -> ( usize , Option < usize > ) ;
42
40
43
41
/// Returns the value that would be obtained by taking the *successor*
44
42
/// of `self` `count` times.
@@ -169,7 +167,7 @@ pub trait Step: Clone + PartialOrd + Sized {
169
167
/// For any `a`:
170
168
///
171
169
/// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)`
172
- /// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`,
170
+ /// * if there exists `b`, `n` such that `steps_between(&b, &a) == (n, Some(n) )`,
173
171
/// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`.
174
172
/// * Corollary: `Step::backward_unchecked(a, 0)` is always safe.
175
173
///
@@ -261,12 +259,13 @@ macro_rules! step_integer_impls {
261
259
step_unsigned_methods!( ) ;
262
260
263
261
#[ inline]
264
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
262
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
265
263
if * start <= * end {
266
264
// This relies on $u_narrower <= usize
267
- Some ( ( * end - * start) as usize )
265
+ let steps = ( * end - * start) as usize ;
266
+ ( steps, Some ( steps) )
268
267
} else {
269
- None
268
+ ( 0 , None )
270
269
}
271
270
}
272
271
@@ -294,16 +293,17 @@ macro_rules! step_integer_impls {
294
293
step_signed_methods!( $u_narrower) ;
295
294
296
295
#[ inline]
297
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
296
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
298
297
if * start <= * end {
299
298
// This relies on $i_narrower <= usize
300
299
//
301
300
// Casting to isize extends the width but preserves the sign.
302
301
// Use wrapping_sub in isize space and cast to usize to compute
303
302
// the difference that might not fit inside the range of isize.
304
- Some ( ( * end as isize ) . wrapping_sub( * start as isize ) as usize )
303
+ let steps = ( * end as isize ) . wrapping_sub( * start as isize ) as usize ;
304
+ ( steps, Some ( steps) )
305
305
} else {
306
- None
306
+ ( 0 , None )
307
307
}
308
308
}
309
309
@@ -359,11 +359,15 @@ macro_rules! step_integer_impls {
359
359
step_unsigned_methods!( ) ;
360
360
361
361
#[ inline]
362
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
362
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
363
363
if * start <= * end {
364
- usize :: try_from( * end - * start) . ok( )
364
+ if let Ok ( steps) = usize :: try_from( * end - * start) {
365
+ ( steps, Some ( steps) )
366
+ } else {
367
+ ( usize :: MAX , None )
368
+ }
365
369
} else {
366
- None
370
+ ( 0 , None )
367
371
}
368
372
}
369
373
@@ -385,16 +389,22 @@ macro_rules! step_integer_impls {
385
389
step_signed_methods!( $u_wider) ;
386
390
387
391
#[ inline]
388
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
392
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
389
393
if * start <= * end {
390
394
match end. checked_sub( * start) {
391
- Some ( result) => usize :: try_from( result) . ok( ) ,
395
+ Some ( result) => {
396
+ if let Ok ( steps) = usize :: try_from( result) {
397
+ ( steps, Some ( steps) )
398
+ } else {
399
+ ( usize :: MAX , None )
400
+ }
401
+ }
392
402
// If the difference is too big for e.g. i128,
393
403
// it's also gonna be too big for usize with fewer bits.
394
- None => None ,
404
+ None => ( usize :: MAX , None ) ,
395
405
}
396
406
} else {
397
- None
407
+ ( 0 , None )
398
408
}
399
409
}
400
410
@@ -433,18 +443,26 @@ step_integer_impls! {
433
443
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
434
444
impl Step for char {
435
445
#[ inline]
436
- fn steps_between ( & start: & char , & end: & char ) -> Option < usize > {
446
+ fn steps_between ( & start: & char , & end: & char ) -> ( usize , Option < usize > ) {
437
447
let start = start as u32 ;
438
448
let end = end as u32 ;
439
449
if start <= end {
440
450
let count = end - start;
441
451
if start < 0xD800 && 0xE000 <= end {
442
- usize:: try_from ( count - 0x800 ) . ok ( )
452
+ if let Ok ( steps) = usize:: try_from ( count - 0x800 ) {
453
+ ( steps, Some ( steps) )
454
+ } else {
455
+ ( usize:: MAX , None )
456
+ }
443
457
} else {
444
- usize:: try_from ( count) . ok ( )
458
+ if let Ok ( steps) = usize:: try_from ( count) {
459
+ ( steps, Some ( steps) )
460
+ } else {
461
+ ( usize:: MAX , None )
462
+ }
445
463
}
446
464
} else {
447
- None
465
+ ( 0 , None )
448
466
}
449
467
}
450
468
@@ -512,7 +530,7 @@ impl Step for char {
512
530
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
513
531
impl Step for AsciiChar {
514
532
#[ inline]
515
- fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> Option < usize > {
533
+ fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> ( usize , Option < usize > ) {
516
534
Step :: steps_between ( & start. to_u8 ( ) , & end. to_u8 ( ) )
517
535
}
518
536
@@ -554,7 +572,7 @@ impl Step for AsciiChar {
554
572
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
555
573
impl Step for Ipv4Addr {
556
574
#[ inline]
557
- fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> Option < usize > {
575
+ fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> ( usize , Option < usize > ) {
558
576
u32:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
559
577
}
560
578
@@ -586,7 +604,7 @@ impl Step for Ipv4Addr {
586
604
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
587
605
impl Step for Ipv6Addr {
588
606
#[ inline]
589
- fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> Option < usize > {
607
+ fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> ( usize , Option < usize > ) {
590
608
u128:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
591
609
}
592
610
@@ -690,11 +708,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
690
708
691
709
#[ inline]
692
710
default fn spec_advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
693
- let available = if self . start <= self . end {
694
- Step :: steps_between ( & self . start , & self . end ) . unwrap_or ( usize:: MAX )
695
- } else {
696
- 0
697
- } ;
711
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
712
+ let available = steps. 1 . unwrap_or ( steps. 0 ) ;
698
713
699
714
let taken = available. min ( n) ;
700
715
@@ -731,11 +746,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
731
746
732
747
#[ inline]
733
748
default fn spec_advance_back_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
734
- let available = if self . start <= self . end {
735
- Step :: steps_between ( & self . start , & self . end ) . unwrap_or ( usize:: MAX )
736
- } else {
737
- 0
738
- } ;
749
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
750
+ let available = steps. 1 . unwrap_or ( steps. 0 ) ;
739
751
740
752
let taken = available. min ( n) ;
741
753
@@ -775,11 +787,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
775
787
776
788
#[ inline]
777
789
fn spec_advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
778
- let available = if self . start <= self . end {
779
- Step :: steps_between ( & self . start , & self . end ) . unwrap_or ( usize:: MAX )
780
- } else {
781
- 0
782
- } ;
790
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
791
+ let available = steps. 1 . unwrap_or ( steps. 0 ) ;
783
792
784
793
let taken = available. min ( n) ;
785
794
@@ -819,11 +828,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
819
828
820
829
#[ inline]
821
830
fn spec_advance_back_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
822
- let available = if self . start <= self . end {
823
- Step :: steps_between ( & self . start , & self . end ) . unwrap_or ( usize:: MAX )
824
- } else {
825
- 0
826
- } ;
831
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
832
+ let available = steps. 1 . unwrap_or ( steps. 0 ) ;
827
833
828
834
let taken = available. min ( n) ;
829
835
@@ -846,8 +852,7 @@ impl<A: Step> Iterator for ops::Range<A> {
846
852
#[ inline]
847
853
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
848
854
if self . start < self . end {
849
- let hint = Step :: steps_between ( & self . start , & self . end ) ;
850
- ( hint. unwrap_or ( usize:: MAX ) , hint)
855
+ Step :: steps_between ( & self . start , & self . end )
851
856
} else {
852
857
( 0 , Some ( 0 ) )
853
858
}
@@ -856,7 +861,7 @@ impl<A: Step> Iterator for ops::Range<A> {
856
861
#[ inline]
857
862
fn count ( self ) -> usize {
858
863
if self . start < self . end {
859
- Step :: steps_between ( & self . start , & self . end ) . expect ( "count overflowed usize" )
864
+ Step :: steps_between ( & self . start , & self . end ) . 1 . expect ( "count overflowed usize" )
860
865
} else {
861
866
0
862
867
}
@@ -980,11 +985,11 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
980
985
// Safety:
981
986
// The following invariants for `Step::steps_between` exist:
982
987
//
983
- // > * `steps_between(&a, &b) == Some(n)` only if `a <= b`
984
- // > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
988
+ // > * `steps_between(&a, &b) == (n, Some(n) )` only if `a <= b`
989
+ // > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != (n, None) `;
985
990
// > this is the case when it would require more than `usize::MAX` steps to
986
991
// > get to `b`
987
- // > * `steps_between(&a, &b) == None` if `a > b`
992
+ // > * `steps_between(&a, &b) == (0, None) ` if `a > b`
988
993
//
989
994
// The first invariant is what is generally required for `TrustedLen` to be
990
995
// sound. The note addendum satisfies an additional `TrustedLen` invariant.
@@ -1253,10 +1258,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
1253
1258
return ( 0 , Some ( 0 ) ) ;
1254
1259
}
1255
1260
1256
- match Step :: steps_between ( & self . start , & self . end ) {
1257
- Some ( hint) => ( hint. saturating_add ( 1 ) , hint. checked_add ( 1 ) ) ,
1258
- None => ( usize:: MAX , None ) ,
1259
- }
1261
+ let hint = Step :: steps_between ( & self . start , & self . end ) ;
1262
+ ( hint. 0 . saturating_add ( 1 ) , hint. 1 . and_then ( |steps| steps. checked_add ( 1 ) ) )
1260
1263
}
1261
1264
1262
1265
#[ inline]
@@ -1266,6 +1269,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
1266
1269
}
1267
1270
1268
1271
Step :: steps_between ( & self . start , & self . end )
1272
+ . 1
1269
1273
. and_then ( |steps| steps. checked_add ( 1 ) )
1270
1274
. expect ( "count overflowed usize" )
1271
1275
}
0 commit comments