Skip to content

Commit 2cd44dd

Browse files
author
Yoshiki Takashima
authored
Implements any_vec::<LENGTH, T>() (rust-lang#1319)
Callout: tests under `tests/kani/Vector/any` are slow, but should terminate within 1 minute. * Added test case for any_vec feature. * Implemented any_vec, arbitrary generator for vectors of T: Invariant * Fixed push. * Unified interface with any_slice. * Loosened trait requirements with Arbitrary. * Fixed typo: sice -> slice. * Implemented variable and exact length vectors. * Adjusted test case to fail. Detailed that failure in comments. * Changed any_vec to use exact_vec for vector generation. Show diff. * Reverted push test case. Separate `any/push_slow.rs` has been added.
1 parent ee1d0c6 commit 2cd44dd

File tree

6 files changed

+112
-0
lines changed

6 files changed

+112
-0
lines changed

library/kani/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
pub mod arbitrary;
77
pub mod invariant;
88
pub mod slice;
9+
pub mod vec;
910

1011
pub use arbitrary::Arbitrary;
1112
pub use invariant::Invariant;

library/kani/src/vec.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
use crate::{any, assume, Invariant};
4+
5+
/// Generates an arbitrary vector whose length is at most MAX_LENGTH.
6+
pub fn any_vec<T, const MAX_LENGTH: usize>() -> Vec<T>
7+
where
8+
T: Invariant,
9+
{
10+
let mut v = exact_vec::<T, MAX_LENGTH>();
11+
let real_length: usize = any();
12+
assume(real_length <= MAX_LENGTH);
13+
unsafe { v.set_len(real_length) };
14+
15+
v
16+
}
17+
18+
/// Generates an arbitrary vector that is exactly EXACT_LENGTH long.
19+
pub fn exact_vec<T, const EXACT_LENGTH: usize>() -> Vec<T>
20+
where
21+
T: Invariant,
22+
{
23+
let boxed_array: Box<[T; EXACT_LENGTH]> = Box::new(any());
24+
<[T]>::into_vec(boxed_array)
25+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
/// Append 2 arbitrary vectors, lengths at most 1 and 2 respectively,
5+
/// and assert they have been appended. This test case takes 53
6+
/// minutes with #[kani::unwind(75)], but takes less than a second
7+
/// with semantically equivalent exact_vec. This performance problem
8+
/// is the subject of issue #1322.
9+
#[kani::proof]
10+
#[kani::unwind(1)]
11+
fn main() {
12+
let mut v1: Vec<u128> = kani::vec::any_vec::<_, 1>();
13+
kani::assume(v1.len() == 1);
14+
let mut v2: Vec<u128> = kani::vec::any_vec::<_, 2>();
15+
kani::assume(v2.len() == 2);
16+
17+
let v1_initial = v1.clone();
18+
let v2_initial = v2.clone();
19+
let l1 = v1.len();
20+
let l2 = v2.len();
21+
22+
v1.append(&mut v2);
23+
assert!(v2.len() == 0);
24+
assert!(v1.len() == (l1 + l2));
25+
26+
assert!(v1[0..l1] == v1_initial);
27+
assert!(v1[l1..] == v2_initial);
28+
}

tests/kani/Vectors/any/push_slow.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
//! Variant of tests/kani/Vector/push.rs using any_vec. Slow due to
5+
//! performance issues involving any_vec. See #1329
6+
#[kani::proof]
7+
fn main() {
8+
let mut v: Vec<isize> = kani::vec::any_vec::<_, 0>();
9+
v.push(72);
10+
v.push(2);
11+
v.push(3);
12+
v.push(4);
13+
v.push(5);
14+
assert!(v[0] == 72);
15+
assert!(v[1] == 2);
16+
assert!(v[2] == 3);
17+
assert!(v[3] == 4);
18+
assert!(v[4] == 5);
19+
}

tests/kani/Vectors/any/resize.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
/// Resizing arbitrary vector of Vec<i64> length at most 5, at least
5+
/// 2. Asserts that the modification occurs, and only on memory that
6+
/// should be changed.
7+
#[kani::proof]
8+
#[kani::unwind(50)]
9+
fn main() {
10+
let mut v: Vec<i64> = kani::vec::exact_vec::<_, 5>();
11+
12+
let initial_length = v.len();
13+
let initial_vector = v.clone();
14+
let arbitrary_padding: i64 = kani::any();
15+
16+
v.resize(initial_length + 1, arbitrary_padding);
17+
assert!(v.len() == initial_length + 1);
18+
assert!(v[v.len() - 1] == arbitrary_padding);
19+
assert!(v[0..initial_length] == initial_vector);
20+
21+
v.resize(initial_length - 1, arbitrary_padding);
22+
assert!(v.len() == initial_length - 1);
23+
assert_eq!(v[..], initial_vector[..initial_length - 1]);
24+
}

tests/kani/Vectors/any/sorting.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
/// Sort an arbitrary Vec<u32> of length 3. Assert that the sorting worked.
5+
#[kani::proof]
6+
#[kani::unwind(4)]
7+
fn main() {
8+
let mut v: Vec<u32> = kani::vec::any_vec::<_, 2>();
9+
kani::assume(v.len() == 2);
10+
11+
if v[0] > v[1] {
12+
v.reverse();
13+
}
14+
assert!(v[0] <= v[1]);
15+
}

0 commit comments

Comments
 (0)