Skip to content

Commit d1a5748

Browse files
committed
Implement BoundedArbitrary for boxed slices
1 parent 7ea1006 commit d1a5748

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

library/kani_core/src/bounded_arbitrary.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ macro_rules! generate_bounded_arbitrary {
1313
fn bounded_any<const N: usize>() -> Self;
1414
}
1515

16+
impl<T: Arbitrary> BoundedArbitrary for alloc::boxed::Box<[T]> {
17+
fn bounded_any<const N: usize>() -> Self {
18+
let len: usize = kani::any_where(|l| *l <= N);
19+
// The following is equivalent to:
20+
// ```
21+
// (0..len).map(|_| T::any()).collect()
22+
// ```
23+
// but leads to more efficient verification
24+
let mut b = alloc::boxed::Box::<[T]>::new_uninit_slice(len);
25+
for i in 0..len {
26+
b[i] = MaybeUninit::new(T::any());
27+
}
28+
unsafe { b.assume_init() }
29+
}
30+
}
31+
1632
impl<T> BoundedArbitrary for Option<T>
1733
where
1834
T: BoundedArbitrary,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Checking harness check_my_boxed_array...
2+
3+
** 6 of 6 cover properties satisfied
4+
5+
VERIFICATION:- SUCCESSFUL
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Check that derive BoundedArbitrary macro works on boxed slices, e.g. `Box<[u16]>`
5+
6+
extern crate kani;
7+
use kani::BoundedArbitrary;
8+
9+
#[derive(BoundedArbitrary)]
10+
#[allow(unused)]
11+
struct StructWithBoxedSlice {
12+
x: i32,
13+
#[bounded]
14+
a: Box<[u16]>,
15+
}
16+
17+
fn first(s: &[u16]) -> Option<u16> {
18+
if s.len() > 0 { Some(s[0]) } else { None }
19+
}
20+
21+
fn tenth(s: &[u16]) -> Option<u16> {
22+
if s.len() >= 10 { Some(s[9]) } else { None }
23+
}
24+
25+
#[kani::proof]
26+
#[kani::unwind(11)]
27+
fn check_my_boxed_array() {
28+
let swbs: StructWithBoxedSlice = kani::bounded_any::<_, 10>();
29+
let f = first(&swbs.a);
30+
kani::cover!(f.is_none());
31+
kani::cover!(f == Some(1));
32+
kani::cover!(f == Some(42));
33+
let t = tenth(&swbs.a);
34+
kani::cover!(t.is_none());
35+
kani::cover!(t == Some(15));
36+
kani::cover!(t == Some(987));
37+
}

0 commit comments

Comments
 (0)