@@ -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()`][std::iter::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,12 @@ 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
+ ( ( * end- * start ) as usize , Some ( ( * end - * start) as usize ) )
268
266
} else {
269
- None
267
+ ( 0 , None )
270
268
}
271
269
}
272
270
@@ -294,16 +292,16 @@ macro_rules! step_integer_impls {
294
292
step_signed_methods!( $u_narrower) ;
295
293
296
294
#[ inline]
297
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
295
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
298
296
if * start <= * end {
299
297
// This relies on $i_narrower <= usize
300
298
//
301
299
// Casting to isize extends the width but preserves the sign.
302
300
// Use wrapping_sub in isize space and cast to usize to compute
303
301
// the difference that might not fit inside the range of isize.
304
- Some ( ( * end as isize ) . wrapping_sub( * start as isize ) as usize )
302
+ ( ( * end as isize ) . wrapping_sub ( * start as isize ) as usize , Some ( ( * end as isize ) . wrapping_sub( * start as isize ) as usize ) )
305
303
} else {
306
- None
304
+ ( 0 , None )
307
305
}
308
306
}
309
307
@@ -359,11 +357,15 @@ macro_rules! step_integer_impls {
359
357
step_unsigned_methods!( ) ;
360
358
361
359
#[ inline]
362
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
360
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
363
361
if * start <= * end {
364
- usize :: try_from( * end - * start) . ok( )
362
+ if let Ok ( steps) = usize :: try_from( * end - * start) {
363
+ ( steps, Some ( steps) )
364
+ } else{
365
+ ( usize :: MAX , None )
366
+ }
365
367
} else {
366
- None
368
+ ( 0 , None )
367
369
}
368
370
}
369
371
@@ -385,16 +387,22 @@ macro_rules! step_integer_impls {
385
387
step_signed_methods!( $u_wider) ;
386
388
387
389
#[ inline]
388
- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
390
+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
389
391
if * start <= * end {
390
392
match end. checked_sub( * start) {
391
- Some ( result) => usize :: try_from( result) . ok( ) ,
393
+ Some ( result) => {
394
+ if let Ok ( steps) = usize :: try_from( result) {
395
+ ( steps, Some ( steps) )
396
+ } else{
397
+ ( usize :: MAX , None )
398
+ }
399
+ }
392
400
// If the difference is too big for e.g. i128,
393
401
// it's also gonna be too big for usize with fewer bits.
394
- None => None ,
402
+ None => ( usize :: MAX , None ) ,
395
403
}
396
404
} else {
397
- None
405
+ ( 0 , None )
398
406
}
399
407
}
400
408
@@ -433,18 +441,26 @@ step_integer_impls! {
433
441
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
434
442
impl Step for char {
435
443
#[ inline]
436
- fn steps_between ( & start: & char , & end: & char ) -> Option < usize > {
444
+ fn steps_between ( & start: & char , & end: & char ) -> ( usize , Option < usize > ) {
437
445
let start = start as u32 ;
438
446
let end = end as u32 ;
439
447
if start <= end {
440
448
let count = end - start;
441
449
if start < 0xD800 && 0xE000 <= end {
442
- usize:: try_from ( count - 0x800 ) . ok ( )
450
+ if let Ok ( steps) = usize:: try_from ( count - 0x800 ) {
451
+ ( steps, Some ( steps) )
452
+ } else {
453
+ ( usize:: MAX , None )
454
+ }
443
455
} else {
444
- usize:: try_from ( count) . ok ( )
456
+ if let Ok ( steps) = usize:: try_from ( count) {
457
+ ( steps, Some ( steps) )
458
+ } else {
459
+ ( usize:: MAX , None )
460
+ }
445
461
}
446
462
} else {
447
- None
463
+ ( 0 , None )
448
464
}
449
465
}
450
466
@@ -512,7 +528,7 @@ impl Step for char {
512
528
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
513
529
impl Step for AsciiChar {
514
530
#[ inline]
515
- fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> Option < usize > {
531
+ fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> ( usize , Option < usize > ) {
516
532
Step :: steps_between ( & start. to_u8 ( ) , & end. to_u8 ( ) )
517
533
}
518
534
@@ -554,7 +570,7 @@ impl Step for AsciiChar {
554
570
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
555
571
impl Step for Ipv4Addr {
556
572
#[ inline]
557
- fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> Option < usize > {
573
+ fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> ( usize , Option < usize > ) {
558
574
u32:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
559
575
}
560
576
@@ -586,7 +602,7 @@ impl Step for Ipv4Addr {
586
602
#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
587
603
impl Step for Ipv6Addr {
588
604
#[ inline]
589
- fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> Option < usize > {
605
+ fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> ( usize , Option < usize > ) {
590
606
u128:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
591
607
}
592
608
@@ -690,11 +706,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
690
706
691
707
#[ inline]
692
708
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
- } ;
709
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
710
+ let available = if let Some ( steps) = steps. 1 { steps } else { steps. 0 } ;
698
711
699
712
let taken = available. min ( n) ;
700
713
@@ -731,11 +744,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
731
744
732
745
#[ inline]
733
746
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
- } ;
747
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
748
+ let available = if let Some ( steps) = steps. 1 { steps } else { steps. 0 } ;
739
749
740
750
let taken = available. min ( n) ;
741
751
@@ -775,11 +785,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
775
785
776
786
#[ inline]
777
787
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
- } ;
788
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
789
+ let available = if let Some ( steps) = steps. 1 { steps } else { steps. 0 } ;
783
790
784
791
let taken = available. min ( n) ;
785
792
@@ -819,11 +826,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
819
826
820
827
#[ inline]
821
828
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
- } ;
829
+ let steps = Step :: steps_between ( & self . start , & self . end ) ;
830
+ let available = if let Some ( steps) = steps. 1 { steps } else { steps. 0 } ;
827
831
828
832
let taken = available. min ( n) ;
829
833
@@ -845,18 +849,13 @@ impl<A: Step> Iterator for ops::Range<A> {
845
849
846
850
#[ inline]
847
851
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
848
- if self . start < self . end {
849
- let hint = Step :: steps_between ( & self . start , & self . end ) ;
850
- ( hint. unwrap_or ( usize:: MAX ) , hint)
851
- } else {
852
- ( 0 , Some ( 0 ) )
853
- }
852
+ Step :: steps_between ( & self . start , & self . end )
854
853
}
855
854
856
855
#[ inline]
857
856
fn count ( self ) -> usize {
858
857
if self . start < self . end {
859
- Step :: steps_between ( & self . start , & self . end ) . expect ( "count overflowed usize" )
858
+ Step :: steps_between ( & self . start , & self . end ) . 1 . expect ( "count overflowed usize" )
860
859
} else {
861
860
0
862
861
}
@@ -980,11 +979,11 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
980
979
// Safety:
981
980
// The following invariants for `Step::steps_between` exist:
982
981
//
983
- // > * `steps_between(&a, &b) == Some(n)` only if `a <= b`
984
- // > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
982
+ // > * `steps_between(&a, &b) == (n, Some(n) )` only if `a <= b`
983
+ // > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != (n, None) `;
985
984
// > this is the case when it would require more than `usize::MAX` steps to
986
985
// > get to `b`
987
- // > * `steps_between(&a, &b) == None` if `a > b`
986
+ // > * `steps_between(&a, &b) == (0, None) ` if `a > b`
988
987
//
989
988
// The first invariant is what is generally required for `TrustedLen` to be
990
989
// sound. The note addendum satisfies an additional `TrustedLen` invariant.
@@ -1253,10 +1252,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
1253
1252
return ( 0 , Some ( 0 ) ) ;
1254
1253
}
1255
1254
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
- }
1255
+ let hint = Step :: steps_between ( & self . start , & self . end ) ;
1256
+ ( hint. 0 . saturating_add ( 1 ) , hint. 1 . and_then ( |steps| steps. checked_add ( 1 ) ) )
1260
1257
}
1261
1258
1262
1259
#[ inline]
@@ -1266,6 +1263,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
1266
1263
}
1267
1264
1268
1265
Step :: steps_between ( & self . start , & self . end )
1266
+ . 1
1269
1267
. and_then ( |steps| steps. checked_add ( 1 ) )
1270
1268
. expect ( "count overflowed usize" )
1271
1269
}
0 commit comments