Skip to content

Commit 536e013

Browse files
authored
Implement BoundedArbitrary for boxed slices (#4340)
Implement the `BoundedArbitrary` trait for boxed slices to allow `#[derive(BoundedArbitrary)]` to work for structs with boxed slices, e.g.: ```rust struct Foo { s: Box<[i32]> } ``` By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent 082dc35 commit 536e013

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

library/kani/src/bounded_arbitrary.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
66
use kani::{Arbitrary, BoundedArbitrary};
77

8+
impl<T: Arbitrary> BoundedArbitrary for Box<[T]> {
9+
fn bounded_any<const N: usize>() -> Self {
10+
let len: usize = kani::any_where(|l| *l <= N);
11+
// The following is equivalent to:
12+
// ```
13+
// (0..len).map(|_| T::any()).collect()
14+
// ```
15+
// but leads to more efficient verification
16+
let mut b = Box::<[T]>::new_uninit_slice(len);
17+
for i in 0..len {
18+
b[i] = std::mem::MaybeUninit::new(T::any());
19+
}
20+
unsafe { b.assume_init() }
21+
}
22+
}
23+
824
// This implementation overlaps with `kani::any_vec` in `kani/library/kani/src/vec.rs`.
925
// This issue `https://github.com/model-checking/kani/issues/4027` tracks deprecating
1026
// `kani::any_vec` in favor of this implementation.
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)