@@ -5508,4 +5508,376 @@ mod verify {
55085508 let mut a: [ u8 ; 100 ] = kani:: any ( ) ;
55095509 a. reverse ( ) ;
55105510 }
5511+
5512+ // --- Challenge #17: Slice harnesses ---
5513+ const SLICE_LEN : usize = 5 ;
5514+
5515+ #[ kani:: proof]
5516+ fn check_get_unchecked ( ) {
5517+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5518+ let s: & [ i32 ] = & arr;
5519+ let idx: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5520+ let val = unsafe { s. get_unchecked ( idx) } ;
5521+ assert_eq ! ( * val, arr[ idx] ) ;
5522+ }
5523+
5524+ #[ kani:: proof]
5525+ fn check_get_unchecked_mut ( ) {
5526+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5527+ let idx: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5528+ let s: & mut [ i32 ] = & mut arr;
5529+ let val = unsafe { s. get_unchecked_mut ( idx) } ;
5530+ * val = 42 ;
5531+ assert_eq ! ( arr[ idx] , 42 ) ;
5532+ }
5533+
5534+ #[ kani:: proof]
5535+ fn check_swap_unchecked ( ) {
5536+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5537+ let a: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5538+ let b: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5539+ let orig_a = arr[ a] ;
5540+ let orig_b = arr[ b] ;
5541+ unsafe { arr. swap_unchecked ( a, b) } ;
5542+ assert_eq ! ( arr[ a] , orig_b) ;
5543+ assert_eq ! ( arr[ b] , orig_a) ;
5544+ }
5545+
5546+ #[ kani:: proof]
5547+ fn check_as_chunks_unchecked ( ) {
5548+ let arr: [ i32 ; 4 ] = kani:: any ( ) ;
5549+ let s: & [ i32 ] = & arr;
5550+ let chunks: & [ [ i32 ; 2 ] ] = unsafe { s. as_chunks_unchecked :: < 2 > ( ) } ;
5551+ assert_eq ! ( chunks. len( ) , 2 ) ;
5552+ assert_eq ! ( chunks[ 0 ] [ 0 ] , arr[ 0 ] ) ;
5553+ assert_eq ! ( chunks[ 1 ] [ 1 ] , arr[ 3 ] ) ;
5554+ }
5555+
5556+ #[ kani:: proof]
5557+ fn check_as_chunks_unchecked_mut ( ) {
5558+ let mut arr: [ i32 ; 4 ] = kani:: any ( ) ;
5559+ let s: & mut [ i32 ] = & mut arr;
5560+ let chunks: & mut [ [ i32 ; 2 ] ] = unsafe { s. as_chunks_unchecked_mut :: < 2 > ( ) } ;
5561+ assert_eq ! ( chunks. len( ) , 2 ) ;
5562+ chunks[ 0 ] [ 0 ] = 99 ;
5563+ assert_eq ! ( arr[ 0 ] , 99 ) ;
5564+ }
5565+
5566+ #[ kani:: proof]
5567+ fn check_split_at_unchecked ( ) {
5568+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5569+ let s: & [ i32 ] = & arr;
5570+ let mid: usize = kani:: any_where ( |& m: & usize | m <= SLICE_LEN ) ;
5571+ let ( left, right) = unsafe { s. split_at_unchecked ( mid) } ;
5572+ assert_eq ! ( left. len( ) , mid) ;
5573+ assert_eq ! ( right. len( ) , SLICE_LEN - mid) ;
5574+ }
5575+
5576+ #[ kani:: proof]
5577+ fn check_split_at_mut_unchecked ( ) {
5578+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5579+ let mid: usize = kani:: any_where ( |& m: & usize | m <= SLICE_LEN ) ;
5580+ let s: & mut [ i32 ] = & mut arr;
5581+ let ( left, right) = unsafe { s. split_at_mut_unchecked ( mid) } ;
5582+ assert_eq ! ( left. len( ) , mid) ;
5583+ assert_eq ! ( right. len( ) , SLICE_LEN - mid) ;
5584+ }
5585+
5586+ #[ kani:: proof]
5587+ fn check_get_disjoint_unchecked_mut ( ) {
5588+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5589+ let a: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5590+ let b: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5591+ kani:: assume ( a != b) ;
5592+ let s: & mut [ i32 ] = & mut arr;
5593+ let [ ra, rb] = unsafe { s. get_disjoint_unchecked_mut ( [ a, b] ) } ;
5594+ * ra = 10 ;
5595+ * rb = 20 ;
5596+ assert_eq ! ( arr[ a] , 10 ) ;
5597+ assert_eq ! ( arr[ b] , 20 ) ;
5598+ }
5599+
5600+ #[ kani:: proof]
5601+ fn check_first_chunk ( ) {
5602+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5603+ let s: & [ i32 ] = & arr;
5604+ let chunk: Option < & [ i32 ; 3 ] > = s. first_chunk :: < 3 > ( ) ;
5605+ assert ! ( chunk. is_some( ) ) ;
5606+ assert_eq ! ( chunk. unwrap( ) [ 0 ] , arr[ 0 ] ) ;
5607+ assert_eq ! ( chunk. unwrap( ) [ 2 ] , arr[ 2 ] ) ;
5608+ }
5609+
5610+ #[ kani:: proof]
5611+ fn check_first_chunk_mut ( ) {
5612+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5613+ let s: & mut [ i32 ] = & mut arr;
5614+ let chunk: Option < & mut [ i32 ; 3 ] > = s. first_chunk_mut :: < 3 > ( ) ;
5615+ assert ! ( chunk. is_some( ) ) ;
5616+ chunk. unwrap ( ) [ 0 ] = 77 ;
5617+ assert_eq ! ( arr[ 0 ] , 77 ) ;
5618+ }
5619+
5620+ #[ kani:: proof]
5621+ fn check_split_first_chunk ( ) {
5622+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5623+ let s: & [ i32 ] = & arr;
5624+ let result: Option < ( & [ i32 ; 2 ] , & [ i32 ] ) > = s. split_first_chunk :: < 2 > ( ) ;
5625+ assert ! ( result. is_some( ) ) ;
5626+ let ( head, tail) = result. unwrap ( ) ;
5627+ assert_eq ! ( head[ 0 ] , arr[ 0 ] ) ;
5628+ assert_eq ! ( tail. len( ) , 3 ) ;
5629+ }
5630+
5631+ #[ kani:: proof]
5632+ fn check_split_first_chunk_mut ( ) {
5633+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5634+ let s: & mut [ i32 ] = & mut arr;
5635+ let result: Option < ( & mut [ i32 ; 2 ] , & mut [ i32 ] ) > = s. split_first_chunk_mut :: < 2 > ( ) ;
5636+ assert ! ( result. is_some( ) ) ;
5637+ let ( head, tail) = result. unwrap ( ) ;
5638+ head[ 0 ] = 55 ;
5639+ assert_eq ! ( tail. len( ) , 3 ) ;
5640+ }
5641+
5642+ #[ kani:: proof]
5643+ fn check_split_last_chunk ( ) {
5644+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5645+ let s: & [ i32 ] = & arr;
5646+ let result: Option < ( & [ i32 ] , & [ i32 ; 2 ] ) > = s. split_last_chunk :: < 2 > ( ) ;
5647+ assert ! ( result. is_some( ) ) ;
5648+ let ( init, last) = result. unwrap ( ) ;
5649+ assert_eq ! ( init. len( ) , 3 ) ;
5650+ assert_eq ! ( last[ 1 ] , arr[ 4 ] ) ;
5651+ }
5652+
5653+ #[ kani:: proof]
5654+ fn check_split_last_chunk_mut ( ) {
5655+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5656+ let s: & mut [ i32 ] = & mut arr;
5657+ let result: Option < ( & mut [ i32 ] , & mut [ i32 ; 2 ] ) > = s. split_last_chunk_mut :: < 2 > ( ) ;
5658+ assert ! ( result. is_some( ) ) ;
5659+ let ( _init, last) = result. unwrap ( ) ;
5660+ last[ 0 ] = 88 ;
5661+ assert_eq ! ( arr[ 3 ] , 88 ) ;
5662+ }
5663+
5664+ #[ kani:: proof]
5665+ fn check_last_chunk ( ) {
5666+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5667+ let s: & [ i32 ] = & arr;
5668+ let chunk: Option < & [ i32 ; 3 ] > = s. last_chunk :: < 3 > ( ) ;
5669+ assert ! ( chunk. is_some( ) ) ;
5670+ assert_eq ! ( chunk. unwrap( ) [ 2 ] , arr[ 4 ] ) ;
5671+ }
5672+
5673+ #[ kani:: proof]
5674+ fn check_last_chunk_mut ( ) {
5675+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5676+ let s: & mut [ i32 ] = & mut arr;
5677+ let chunk: Option < & mut [ i32 ; 3 ] > = s. last_chunk_mut :: < 3 > ( ) ;
5678+ assert ! ( chunk. is_some( ) ) ;
5679+ chunk. unwrap ( ) [ 0 ] = 66 ;
5680+ assert_eq ! ( arr[ 2 ] , 66 ) ;
5681+ }
5682+
5683+ #[ kani:: proof]
5684+ fn check_as_chunks ( ) {
5685+ let arr: [ i32 ; 4 ] = kani:: any ( ) ;
5686+ let s: & [ i32 ] = & arr;
5687+ let ( chunks, remainder) = s. as_chunks :: < 2 > ( ) ;
5688+ assert_eq ! ( chunks. len( ) , 2 ) ;
5689+ assert_eq ! ( remainder. len( ) , 0 ) ;
5690+ assert_eq ! ( chunks[ 0 ] [ 0 ] , arr[ 0 ] ) ;
5691+ }
5692+
5693+ #[ kani:: proof]
5694+ fn check_as_chunks_mut ( ) {
5695+ let mut arr: [ i32 ; 4 ] = kani:: any ( ) ;
5696+ let s: & mut [ i32 ] = & mut arr;
5697+ let ( chunks, remainder) = s. as_chunks_mut :: < 2 > ( ) ;
5698+ assert_eq ! ( chunks. len( ) , 2 ) ;
5699+ assert_eq ! ( remainder. len( ) , 0 ) ;
5700+ chunks[ 1 ] [ 1 ] = 33 ;
5701+ assert_eq ! ( arr[ 3 ] , 33 ) ;
5702+ }
5703+
5704+ #[ kani:: proof]
5705+ fn check_as_rchunks ( ) {
5706+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5707+ let s: & [ i32 ] = & arr;
5708+ let ( remainder, chunks) = s. as_rchunks :: < 2 > ( ) ;
5709+ assert_eq ! ( chunks. len( ) , 2 ) ;
5710+ assert_eq ! ( remainder. len( ) , 1 ) ;
5711+ assert_eq ! ( remainder[ 0 ] , arr[ 0 ] ) ;
5712+ }
5713+
5714+ #[ kani:: proof]
5715+ fn check_split_at_checked ( ) {
5716+ let arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5717+ let s: & [ i32 ] = & arr;
5718+ let mid: usize = kani:: any ( ) ;
5719+ if mid <= SLICE_LEN {
5720+ let result = s. split_at_checked ( mid) ;
5721+ assert ! ( result. is_some( ) ) ;
5722+ let ( l, r) = result. unwrap ( ) ;
5723+ assert_eq ! ( l. len( ) , mid) ;
5724+ assert_eq ! ( r. len( ) , SLICE_LEN - mid) ;
5725+ } else {
5726+ assert ! ( s. split_at_checked( mid) . is_none( ) ) ;
5727+ }
5728+ }
5729+
5730+ #[ kani:: proof]
5731+ fn check_split_at_mut_checked ( ) {
5732+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5733+ let mid: usize = kani:: any ( ) ;
5734+ let s: & mut [ i32 ] = & mut arr;
5735+ if mid <= SLICE_LEN {
5736+ let result = s. split_at_mut_checked ( mid) ;
5737+ assert ! ( result. is_some( ) ) ;
5738+ let ( l, r) = result. unwrap ( ) ;
5739+ assert_eq ! ( l. len( ) , mid) ;
5740+ assert_eq ! ( r. len( ) , SLICE_LEN - mid) ;
5741+ } else {
5742+ let s2: & mut [ i32 ] = & mut arr;
5743+ assert ! ( s2. split_at_mut_checked( mid) . is_none( ) ) ;
5744+ }
5745+ }
5746+
5747+ #[ kani:: proof]
5748+ fn check_copy_from_slice ( ) {
5749+ let src: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5750+ let mut dst: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5751+ dst. copy_from_slice ( & src) ;
5752+ assert_eq ! ( dst, src) ;
5753+ }
5754+
5755+ #[ kani:: proof]
5756+ fn check_copy_within ( ) {
5757+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5758+ let src_start: usize = kani:: any ( ) ;
5759+ let src_end: usize = kani:: any ( ) ;
5760+ let dest: usize = kani:: any ( ) ;
5761+ kani:: assume ( src_start <= src_end) ;
5762+ kani:: assume ( src_end <= SLICE_LEN ) ;
5763+ kani:: assume ( dest <= SLICE_LEN - ( src_end - src_start) ) ;
5764+ arr. copy_within ( src_start..src_end, dest) ;
5765+ }
5766+
5767+ #[ kani:: proof]
5768+ fn check_swap_with_slice ( ) {
5769+ let mut a: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5770+ let mut b: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5771+ let orig_a = a;
5772+ let orig_b = b;
5773+ a. swap_with_slice ( & mut b) ;
5774+ assert_eq ! ( a, orig_b) ;
5775+ assert_eq ! ( b, orig_a) ;
5776+ }
5777+
5778+ #[ kani:: proof]
5779+ #[ kani:: unwind( 6 ) ]
5780+ fn check_binary_search_by ( ) {
5781+ let a: i32 = kani:: any ( ) ;
5782+ let b: i32 = kani:: any ( ) ;
5783+ let c: i32 = kani:: any ( ) ;
5784+ kani:: assume ( a <= b && b <= c) ;
5785+ let arr = [ a, b, c] ;
5786+ let target: i32 = kani:: any ( ) ;
5787+ let result = arr. binary_search_by ( |probe| probe. cmp ( & target) ) ;
5788+ match result {
5789+ Ok ( idx) => assert ! ( idx < 3 && arr[ idx] == target) ,
5790+ Err ( idx) => assert ! ( idx <= 3 ) ,
5791+ }
5792+ }
5793+
5794+ #[ kani:: proof]
5795+ #[ kani:: unwind( 6 ) ]
5796+ fn check_partition_dedup_by ( ) {
5797+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5798+ let ( dedup, dups) = arr. partition_dedup_by ( |a, b| * a == * b) ;
5799+ assert_eq ! ( dedup. len( ) + dups. len( ) , SLICE_LEN ) ;
5800+ }
5801+
5802+ #[ kani:: proof]
5803+ #[ kani:: unwind( 5 ) ]
5804+ fn check_rotate_left ( ) {
5805+ let mut arr: [ i32 ; 2 ] = kani:: any ( ) ;
5806+ let k: usize = kani:: any ( ) ;
5807+ kani:: assume ( k <= 2 ) ;
5808+ arr. rotate_left ( k) ;
5809+ }
5810+
5811+ #[ kani:: proof]
5812+ #[ kani:: unwind( 5 ) ]
5813+ fn check_rotate_right ( ) {
5814+ let mut arr: [ i32 ; 2 ] = kani:: any ( ) ;
5815+ let k: usize = kani:: any ( ) ;
5816+ kani:: assume ( k <= 2 ) ;
5817+ arr. rotate_right ( k) ;
5818+ }
5819+
5820+ #[ kani:: proof]
5821+ fn check_as_flattened ( ) {
5822+ let arr: [ [ i32 ; 2 ] ; 3 ] = kani:: any ( ) ;
5823+ let s: & [ [ i32 ; 2 ] ] = & arr;
5824+ let flat: & [ i32 ] = s. as_flattened ( ) ;
5825+ assert_eq ! ( flat. len( ) , 6 ) ;
5826+ assert_eq ! ( flat[ 0 ] , arr[ 0 ] [ 0 ] ) ;
5827+ assert_eq ! ( flat[ 5 ] , arr[ 2 ] [ 1 ] ) ;
5828+ }
5829+
5830+ #[ kani:: proof]
5831+ fn check_as_flattened_mut ( ) {
5832+ let mut arr: [ [ i32 ; 2 ] ; 3 ] = kani:: any ( ) ;
5833+ let s: & mut [ [ i32 ; 2 ] ] = & mut arr;
5834+ let flat: & mut [ i32 ] = s. as_flattened_mut ( ) ;
5835+ assert_eq ! ( flat. len( ) , 6 ) ;
5836+ flat[ 0 ] = 42 ;
5837+ assert_eq ! ( arr[ 0 ] [ 0 ] , 42 ) ;
5838+ }
5839+
5840+ #[ kani:: proof]
5841+ fn check_get_disjoint_mut ( ) {
5842+ let mut arr: [ i32 ; SLICE_LEN ] = kani:: any ( ) ;
5843+ let a: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5844+ let b: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5845+ kani:: assume ( a != b) ;
5846+ let result = arr. get_disjoint_mut ( [ a, b] ) ;
5847+ assert ! ( result. is_ok( ) ) ;
5848+ let [ ra, rb] = result. unwrap ( ) ;
5849+ * ra = 1 ;
5850+ * rb = 2 ;
5851+ assert_eq ! ( arr[ a] , 1 ) ;
5852+ assert_eq ! ( arr[ b] , 2 ) ;
5853+ }
5854+
5855+ #[ kani:: proof]
5856+ fn check_get_disjoint_check_valid ( ) {
5857+ let a: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5858+ let b: usize = kani:: any_where ( |& i: & usize | i < SLICE_LEN ) ;
5859+ let indices = [ a, b] ;
5860+ let result = get_disjoint_check_valid ( & indices, SLICE_LEN ) ;
5861+ if a == b {
5862+ assert ! ( result. is_err( ) ) ;
5863+ } else {
5864+ assert ! ( result. is_ok( ) ) ;
5865+ }
5866+ }
5867+
5868+ #[ kani:: proof]
5869+ fn check_as_simd ( ) {
5870+ let arr: [ f32 ; 4 ] = kani:: any ( ) ;
5871+ let s: & [ f32 ] = & arr;
5872+ let ( prefix, middle, suffix) = s. as_simd :: < 4 > ( ) ;
5873+ assert_eq ! ( prefix. len( ) + middle. len( ) * 4 + suffix. len( ) , 4 ) ;
5874+ }
5875+
5876+ #[ kani:: proof]
5877+ fn check_as_simd_mut ( ) {
5878+ let mut arr: [ f32 ; 4 ] = kani:: any ( ) ;
5879+ let s: & mut [ f32 ] = & mut arr;
5880+ let ( prefix, middle, suffix) = s. as_simd_mut :: < 4 > ( ) ;
5881+ assert_eq ! ( prefix. len( ) + middle. len( ) * 4 + suffix. len( ) , 4 ) ;
5882+ }
55115883}
0 commit comments