@@ -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()`][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,13 @@ 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+ let steps = ( * end - * start) as usize ;
266+ ( steps, Some ( steps) )
268267 } else {
269- None
268+ ( 0 , None )
270269 }
271270 }
272271
@@ -294,16 +293,17 @@ macro_rules! step_integer_impls {
294293 step_signed_methods!( $u_narrower) ;
295294
296295 #[ inline]
297- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
296+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
298297 if * start <= * end {
299298 // This relies on $i_narrower <= usize
300299 //
301300 // Casting to isize extends the width but preserves the sign.
302301 // Use wrapping_sub in isize space and cast to usize to compute
303302 // 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) )
305305 } else {
306- None
306+ ( 0 , None )
307307 }
308308 }
309309
@@ -359,11 +359,15 @@ macro_rules! step_integer_impls {
359359 step_unsigned_methods!( ) ;
360360
361361 #[ inline]
362- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
362+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
363363 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+ }
365369 } else {
366- None
370+ ( 0 , None )
367371 }
368372 }
369373
@@ -385,16 +389,22 @@ macro_rules! step_integer_impls {
385389 step_signed_methods!( $u_wider) ;
386390
387391 #[ inline]
388- fn steps_between( start: & Self , end: & Self ) -> Option <usize > {
392+ fn steps_between( start: & Self , end: & Self ) -> ( usize , Option <usize >) {
389393 if * start <= * end {
390394 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+ }
392402 // If the difference is too big for e.g. i128,
393403 // it's also gonna be too big for usize with fewer bits.
394- None => None ,
404+ None => ( usize :: MAX , None ) ,
395405 }
396406 } else {
397- None
407+ ( 0 , None )
398408 }
399409 }
400410
@@ -433,18 +443,26 @@ step_integer_impls! {
433443#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
434444impl Step for char {
435445 #[ inline]
436- fn steps_between ( & start: & char , & end: & char ) -> Option < usize > {
446+ fn steps_between ( & start: & char , & end: & char ) -> ( usize , Option < usize > ) {
437447 let start = start as u32 ;
438448 let end = end as u32 ;
439449 if start <= end {
440450 let count = end - start;
441451 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+ }
443457 } 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+ }
445463 }
446464 } else {
447- None
465+ ( 0 , None )
448466 }
449467 }
450468
@@ -512,7 +530,7 @@ impl Step for char {
512530#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
513531impl Step for AsciiChar {
514532 #[ inline]
515- fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> Option < usize > {
533+ fn steps_between ( & start: & AsciiChar , & end: & AsciiChar ) -> ( usize , Option < usize > ) {
516534 Step :: steps_between ( & start. to_u8 ( ) , & end. to_u8 ( ) )
517535 }
518536
@@ -554,7 +572,7 @@ impl Step for AsciiChar {
554572#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
555573impl Step for Ipv4Addr {
556574 #[ inline]
557- fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> Option < usize > {
575+ fn steps_between ( & start: & Ipv4Addr , & end: & Ipv4Addr ) -> ( usize , Option < usize > ) {
558576 u32:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
559577 }
560578
@@ -586,7 +604,7 @@ impl Step for Ipv4Addr {
586604#[ unstable( feature = "step_trait" , reason = "recently redesigned" , issue = "42168" ) ]
587605impl Step for Ipv6Addr {
588606 #[ inline]
589- fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> Option < usize > {
607+ fn steps_between ( & start: & Ipv6Addr , & end: & Ipv6Addr ) -> ( usize , Option < usize > ) {
590608 u128:: steps_between ( & start. to_bits ( ) , & end. to_bits ( ) )
591609 }
592610
@@ -690,11 +708,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
690708
691709 #[ inline]
692710 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 ) ;
698713
699714 let taken = available. min ( n) ;
700715
@@ -731,11 +746,8 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
731746
732747 #[ inline]
733748 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 ) ;
739751
740752 let taken = available. min ( n) ;
741753
@@ -775,11 +787,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
775787
776788 #[ inline]
777789 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 ) ;
783792
784793 let taken = available. min ( n) ;
785794
@@ -819,11 +828,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
819828
820829 #[ inline]
821830 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 ) ;
827833
828834 let taken = available. min ( n) ;
829835
@@ -846,8 +852,7 @@ impl<A: Step> Iterator for ops::Range<A> {
846852 #[ inline]
847853 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
848854 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 )
851856 } else {
852857 ( 0 , Some ( 0 ) )
853858 }
@@ -856,7 +861,7 @@ impl<A: Step> Iterator for ops::Range<A> {
856861 #[ inline]
857862 fn count ( self ) -> usize {
858863 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" )
860865 } else {
861866 0
862867 }
@@ -980,11 +985,11 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
980985// Safety:
981986// The following invariants for `Step::steps_between` exist:
982987//
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) `;
985990// > this is the case when it would require more than `usize::MAX` steps to
986991// > get to `b`
987- // > * `steps_between(&a, &b) == None` if `a > b`
992+ // > * `steps_between(&a, &b) == (0, None) ` if `a > b`
988993//
989994// The first invariant is what is generally required for `TrustedLen` to be
990995// sound. The note addendum satisfies an additional `TrustedLen` invariant.
@@ -1253,10 +1258,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
12531258 return ( 0 , Some ( 0 ) ) ;
12541259 }
12551260
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 ) ) )
12601263 }
12611264
12621265 #[ inline]
@@ -1266,6 +1269,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
12661269 }
12671270
12681271 Step :: steps_between ( & self . start , & self . end )
1272+ . 1
12691273 . and_then ( |steps| steps. checked_add ( 1 ) )
12701274 . expect ( "count overflowed usize" )
12711275 }
0 commit comments