1+ use safety:: requires;
2+
13use super :: {
24 FusedIterator , TrustedLen , TrustedRandomAccess , TrustedRandomAccessNoCoerce , TrustedStep ,
35} ;
46use crate :: ascii:: Char as AsciiChar ;
7+ #[ cfg( kani) ]
8+ use crate :: kani;
59use crate :: mem;
610use crate :: net:: { Ipv4Addr , Ipv6Addr } ;
711use crate :: num:: NonZero ;
@@ -184,12 +188,14 @@ pub trait Step: Clone + PartialOrd + Sized {
184188// than the signed::MAX value. Therefore `as` casting to the signed type would be incorrect.
185189macro_rules! step_signed_methods {
186190 ( $unsigned: ty) => {
191+ #[ requires( start. checked_add_unsigned( n as $unsigned) . is_some( ) ) ]
187192 #[ inline]
188193 unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
189194 // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
190195 unsafe { start. checked_add_unsigned( n as $unsigned) . unwrap_unchecked( ) }
191196 }
192197
198+ #[ requires( start. checked_sub_unsigned( n as $unsigned) . is_some( ) ) ]
193199 #[ inline]
194200 unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
195201 // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
@@ -200,12 +206,14 @@ macro_rules! step_signed_methods {
200206
201207macro_rules! step_unsigned_methods {
202208 ( ) => {
209+ #[ requires( start. checked_add( n as Self ) . is_some( ) ) ]
203210 #[ inline]
204211 unsafe fn forward_unchecked( start: Self , n: usize ) -> Self {
205212 // SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
206213 unsafe { start. unchecked_add( n as Self ) }
207214 }
208215
216+ #[ requires( start >= ( n as Self ) ) ]
209217 #[ inline]
210218 unsafe fn backward_unchecked( start: Self , n: usize ) -> Self {
211219 // SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
@@ -495,6 +503,13 @@ impl Step for char {
495503 Some ( unsafe { char:: from_u32_unchecked ( res) } )
496504 }
497505
506+ #[ requires( {
507+ ( start as u32 ) . checked_add( count as u32 ) . is_some_and( |dist|
508+ ( start as u32 ) >= 0xD800 ||
509+ dist < 0xD800 ||
510+ dist. checked_add( 0x800 ) . is_some( )
511+ )
512+ } ) ]
498513 #[ inline]
499514 unsafe fn forward_unchecked ( start : char , count : usize ) -> char {
500515 let start = start as u32 ;
@@ -511,6 +526,13 @@ impl Step for char {
511526 unsafe { char:: from_u32_unchecked ( res) }
512527 }
513528
529+ #[ requires( {
530+ ( start as u32 ) . checked_sub( count as u32 ) . is_some_and( |dist|
531+ ( start as u32 ) < 0xE000 ||
532+ dist >= 0xE000 ||
533+ dist. checked_sub( 0x800 ) . is_some( )
534+ )
535+ } ) ]
514536 #[ inline]
515537 unsafe fn backward_unchecked ( start : char , count : usize ) -> char {
516538 let start = start as u32 ;
@@ -549,6 +571,7 @@ impl Step for AsciiChar {
549571 Some ( unsafe { AsciiChar :: from_u8_unchecked ( end) } )
550572 }
551573
574+ #[ requires( count < 256 && start. to_u8( ) . checked_add( count as u8 ) . is_some( ) ) ]
552575 #[ inline]
553576 unsafe fn forward_unchecked ( start : AsciiChar , count : usize ) -> AsciiChar {
554577 // SAFETY: Caller asserts that result is a valid ASCII character,
@@ -559,6 +582,7 @@ impl Step for AsciiChar {
559582 unsafe { AsciiChar :: from_u8_unchecked ( end) }
560583 }
561584
585+ #[ requires( count < 256 && start. to_u8( ) . checked_sub( count as u8 ) . is_some( ) ) ]
562586 #[ inline]
563587 unsafe fn backward_unchecked ( start : AsciiChar , count : usize ) -> AsciiChar {
564588 // SAFETY: Caller asserts that result is a valid ASCII character,
@@ -587,13 +611,15 @@ impl Step for Ipv4Addr {
587611 u32:: backward_checked ( start. to_bits ( ) , count) . map ( Ipv4Addr :: from_bits)
588612 }
589613
614+ #[ requires( start. to_bits( ) . checked_add( count as u32 ) . is_some( ) ) ]
590615 #[ inline]
591616 unsafe fn forward_unchecked ( start : Ipv4Addr , count : usize ) -> Ipv4Addr {
592617 // SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
593618 // this is as safe as the u32 version.
594619 Ipv4Addr :: from_bits ( unsafe { u32:: forward_unchecked ( start. to_bits ( ) , count) } )
595620 }
596621
622+ #[ requires( start. to_bits( ) . checked_sub( count as u32 ) . is_some( ) ) ]
597623 #[ inline]
598624 unsafe fn backward_unchecked ( start : Ipv4Addr , count : usize ) -> Ipv4Addr {
599625 // SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
@@ -619,13 +645,15 @@ impl Step for Ipv6Addr {
619645 u128:: backward_checked ( start. to_bits ( ) , count) . map ( Ipv6Addr :: from_bits)
620646 }
621647
648+ #[ requires( start. to_bits( ) . checked_add( count as u128 ) . is_some( ) ) ]
622649 #[ inline]
623650 unsafe fn forward_unchecked ( start : Ipv6Addr , count : usize ) -> Ipv6Addr {
624651 // SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
625652 // this is as safe as the u128 version.
626653 Ipv6Addr :: from_bits ( unsafe { u128:: forward_unchecked ( start. to_bits ( ) , count) } )
627654 }
628655
656+ #[ requires( start. to_bits( ) . checked_sub( count as u128 ) . is_some( ) ) ]
629657 #[ inline]
630658 unsafe fn backward_unchecked ( start : Ipv6Addr , count : usize ) -> Ipv6Addr {
631659 // SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
0 commit comments