Skip to content

Commit ce992a4

Browse files
authored
Create Arbitrary::any_array() (rust-lang#2199)
Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent f5df11e commit ce992a4

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

library/kani/src/arbitrary.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,27 @@
33

44
//! This module introduces the Arbitrary trait as well as implementation for primitive types and
55
//! other std containers.
6+
67
use std::{
78
marker::{PhantomData, PhantomPinned},
89
num::*,
910
};
1011

1112
/// This trait should be used to generate symbolic variables that represent any valid value of
1213
/// its type.
13-
pub trait Arbitrary {
14+
pub trait Arbitrary
15+
where
16+
Self: Sized,
17+
{
1418
fn any() -> Self;
19+
fn any_array<const MAX_ARRAY_LENGTH: usize>() -> [Self; MAX_ARRAY_LENGTH]
20+
// the requirement defined in the where clause must appear on the `impl`'s method `any_array`
21+
// but also on the corresponding trait's method
22+
where
23+
[(); std::mem::size_of::<[Self; MAX_ARRAY_LENGTH]>()]:,
24+
{
25+
[(); MAX_ARRAY_LENGTH].map(|_| Self::any())
26+
}
1527
}
1628

1729
/// The given type can be represented by an unconstrained symbolic value of size_of::<T>.
@@ -20,8 +32,21 @@ macro_rules! trivial_arbitrary {
2032
impl Arbitrary for $type {
2133
#[inline(always)]
2234
fn any() -> Self {
23-
// This size_of call does not use generic_const_exprs feature. It's inside a macro, and $type isn't generic.
24-
unsafe { crate::any_raw_internal::<$type, { std::mem::size_of::<$type>() }>() }
35+
// This size_of call does not use generic_const_exprs feature. It's inside a macro, and Self isn't generic.
36+
unsafe { crate::any_raw_internal::<Self, { std::mem::size_of::<Self>() }>() }
37+
}
38+
fn any_array<const MAX_ARRAY_LENGTH: usize>() -> [Self; MAX_ARRAY_LENGTH]
39+
where
40+
// `generic_const_exprs` requires all potential errors to be reflected in the signature/header.
41+
// We must repeat the expression in the header, to make sure that if the body can fail the header will also fail.
42+
[(); { std::mem::size_of::<[$type; MAX_ARRAY_LENGTH]>() }]:,
43+
{
44+
unsafe {
45+
crate::any_raw_internal::<
46+
[Self; MAX_ARRAY_LENGTH],
47+
{ std::mem::size_of::<[Self; MAX_ARRAY_LENGTH]>() },
48+
>()
49+
}
2550
}
2651
}
2752
};
@@ -99,9 +124,10 @@ nonzero_arbitrary!(NonZeroIsize, isize);
99124
impl<T, const N: usize> Arbitrary for [T; N]
100125
where
101126
T: Arbitrary,
127+
[(); std::mem::size_of::<[T; N]>()]:,
102128
{
103129
fn any() -> Self {
104-
[(); N].map(|_| T::any())
130+
T::any_array()
105131
}
106132
}
107133

library/kani/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
// Used for rustc_diagnostic_item.
55
#![feature(rustc_attrs)]
6+
// This is required for the optimized version of `any_array()`
7+
#![feature(generic_const_exprs)]
8+
#![allow(incomplete_features)]
69

710
pub mod arbitrary;
811
#[cfg(feature = "concrete_playback")]

library/kani/src/vec.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{any, assume, Arbitrary};
66
pub fn any_vec<T, const MAX_LENGTH: usize>() -> Vec<T>
77
where
88
T: Arbitrary,
9+
[(); std::mem::size_of::<[T; MAX_LENGTH]>()]:,
910
{
1011
let mut v = exact_vec::<T, MAX_LENGTH>();
1112
let real_length: usize = any();
@@ -19,6 +20,7 @@ where
1920
pub fn exact_vec<T, const EXACT_LENGTH: usize>() -> Vec<T>
2021
where
2122
T: Arbitrary,
23+
[(); std::mem::size_of::<[T; EXACT_LENGTH]>()]:,
2224
{
2325
let boxed_array: Box<[T; EXACT_LENGTH]> = Box::new(any());
2426
<[T]>::into_vec(boxed_array)

tests/expected/object-bits/insufficient/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
#[kani::proof]
99
fn main() {
10-
let arr: [i32; 100] = kani::any();
11-
assert_eq!(arr[0], arr[99]);
10+
let mut arr: [i32; 100] = kani::Arbitrary::any_array();
11+
for i in 0..30 {
12+
arr[i] = kani::any();
13+
}
14+
assert!(arr[0] > arr[0] - arr[99]);
1215
}

0 commit comments

Comments
 (0)