@@ -22,23 +22,21 @@ unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u6
2222/// The *predecessor* operation moves towards values that compare lesser.
2323#[ unstable( feature = "step_trait" , issue = "42168" ) ]
2424pub 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()].
2627 ///
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.
2929 ///
3030 /// # Invariants
3131 ///
3232 /// For any `a`, `b`, and `n`:
3333 ///
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 > ) ;
4240
4341 /// Returns the value that would be obtained by taking the *successor*
4442 /// of `self` `count` times.
@@ -169,7 +167,7 @@ pub trait Step: Clone + PartialOrd + Sized {
169167 /// For any `a`:
170168 ///
171169 /// * 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) )`,
173171 /// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`.
174172 /// * Corollary: `Step::backward_unchecked(a, 0)` is always safe.
175173 ///
@@ -261,12 +259,12 @@ macro_rules! step_integer_impls {
261259 step_unsigned_methods!( ) ;
262260
263261 #[ inline]
264- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
262+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
265263 if * start <= * end {
266264 // This relies on $u_narrower <= usize
267- Some ( ( * end - * start) as usize )
265+ ( ( * end- * start ) as usize , Some ( ( * end - * start) as usize ) )
268266 } else {
269- None
267+ ( 0 , None )
270268 }
271269 }
272270
@@ -294,16 +292,16 @@ macro_rules! step_integer_impls {
294292 step_signed_methods!( $u_narrower) ;
295293
296294 #[ inline]
297- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
295+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
298296 if * start <= * end {
299297 // This relies on $i_narrower <= usize
300298 //
301299 // Casting to isize extends the width but preserves the sign.
302300 // Use wrapping_sub in isize space and cast to usize to compute
303301 // 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 ) )
305303 } else {
306- None
304+ ( 0 , None )
307305 }
308306 }
309307
@@ -359,11 +357,15 @@ macro_rules! step_integer_impls {
359357 step_unsigned_methods!( ) ;
360358
361359 #[ inline]
362- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
360+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
363361 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+ }
365367 } else {
366- None
368+ ( 0 , None )
367369 }
368370 }
369371
@@ -385,16 +387,22 @@ macro_rules! step_integer_impls {
385387 step_signed_methods!( $u_wider) ;
386388
387389 #[ inline]
388- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
390+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
389391 if * start <= * end {
390392 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+ }
392400 // If the difference is too big for e.g. i128,
393401 // it's also gonna be too big for usize with fewer bits.
394- None => None ,
402+ None => ( usize :: MAX , None ) ,
395403 }
396404 } else {
397- None
405+ ( 0 , None )
398406 }
399407 }
400408
@@ -433,18 +441,26 @@ step_integer_impls! {
433441#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
434442impl Step for char {
435443 #[ inline]
436- fn steps_between ( & start: & char , & end: & char ) -> Option < usize > {
444+ fn steps_between ( & start: & char , & end: & char ) -> ( usize , Option < usize > ) {
437445 let start = start as u32 ;
438446 let end = end as u32 ;
439447 if start <= end {
440448 let count = end - start;
441449 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+ }
443455 } 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+ }
445461 }
446462 } else {
447- None
463+ ( 0 , None )
448464 }
449465 }
450466
@@ -512,7 +528,7 @@ impl Step for char {
512528#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
513529impl Step for AsciiChar {
514530 #[ inline]
515- fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> Option < usize > {
531+ fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> ( usize , Option < usize > ) {
516532 Step :: steps_between ( & start. to_u8 ( ) , & end. to_u8 ( ) )
517533 }
518534
@@ -554,7 +570,7 @@ impl Step for AsciiChar {
554570#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
555571impl Step for Ipv4Addr {
556572 #[ inline]
557- fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> Option < usize > {
573+ fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> ( usize , Option < usize > ) {
558574 u32:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
559575 }
560576
@@ -586,7 +602,7 @@ impl Step for Ipv4Addr {
586602#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
587603impl Step for Ipv6Addr {
588604 #[ inline]
589- fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> Option < usize > {
605+ fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> ( usize , Option < usize > ) {
590606 u128:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
591607 }
592608
@@ -690,11 +706,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
690706
691707 #[ inline]
692708 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 } ;
698711
699712 let taken = available. min ( n) ;
700713
@@ -731,11 +744,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
731744
732745 #[ inline]
733746 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 } ;
739749
740750 let taken = available. min ( n) ;
741751
@@ -775,11 +785,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
775785
776786 #[ inline]
777787 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 } ;
783790
784791 let taken = available. min ( n) ;
785792
@@ -819,11 +826,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
819826
820827 #[ inline]
821828 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 } ;
827831
828832 let taken = available. min ( n) ;
829833
@@ -845,18 +849,13 @@ impl<A: Step> Iterator for ops::Range<A> {
845849
846850 #[ inline]
847851 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 )
854853 }
855854
856855 #[ inline]
857856 fn count ( self ) -> usize {
858857 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" )
860859 } else {
861860 0
862861 }
@@ -980,11 +979,11 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
980979// Safety:
981980// The following invariants for `Step::steps_between` exist:
982981//
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) `;
985984// > this is the case when it would require more than `usize::MAX` steps to
986985// > get to `b`
987- // > * `steps_between(&a, &b) == None` if `a > b`
986+ // > * `steps_between(&a, &b) == (0, None) ` if `a > b`
988987//
989988// The first invariant is what is generally required for `TrustedLen` to be
990989// sound. The note addendum satisfies an additional `TrustedLen` invariant.
@@ -1253,10 +1252,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
12531252 return ( 0 , Some ( 0 ) ) ;
12541253 }
12551254
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 ) ) )
12601257 }
12611258
12621259 #[ inline]
@@ -1266,6 +1263,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
12661263 }
12671264
12681265 Step :: steps_between ( & self . start , & self . end )
1266+ . 1
12691267 . and_then ( |steps| steps. checked_add ( 1 ) )
12701268 . expect ( "count overflowed usize" )
12711269 }
0 commit comments