Skip to content

Commit 69d8bd3

Browse files
committed
Add loop contracts and harness for Slice::partition_dedup_by
1 parent 3a967e3 commit 69d8bd3

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@
246246
#![feature(unboxed_closures)]
247247
#![feature(unsized_fn_params)]
248248
#![feature(with_negative_coherence)]
249+
#![cfg_attr(kani, feature(proc_macro_hygiene))]
249250
// tidy-alphabetical-end
250251
//
251252
// Target features:

library/core/src/slice/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ use crate::simd::{self, Simd};
1515
use crate::ub_checks::assert_unsafe_precondition;
1616
use crate::{fmt, hint, ptr, slice};
1717

18+
use safety::{requires, ensures};
19+
20+
#[cfg(kani)]
21+
use crate::kani;
22+
1823
#[unstable(
1924
feature = "slice_internals",
2025
issue = "none",
@@ -3362,6 +3367,7 @@ impl<T> [T] {
33623367
// thus `next_read > next_write - 1` is too.
33633368
unsafe {
33643369
// Avoid bounds checks by using raw pointers.
3370+
#[cfg_attr(kani, kani::loop_invariant(next_read <= len && next_read >= next_write && next_write >= 1))]
33653371
while next_read < len {
33663372
let ptr_read = ptr.add(next_read);
33673373
let prev_ptr_write = ptr.add(next_write - 1);
@@ -4912,3 +4918,38 @@ impl<const N: usize> fmt::Display for GetManyMutError<N> {
49124918
fmt::Display::fmt("an index is out of bounds or appeared multiple times in the array", f)
49134919
}
49144920
}
4921+
4922+
#[cfg(kani)]
4923+
#[unstable(feature = "kani", issue = "none")]
4924+
pub mod verify {
4925+
use super::*;
4926+
4927+
pub fn any_slice_of_array<T, const LENGTH: usize>(arr: &[T; LENGTH]) -> &[T] {
4928+
let (from, to) = any_range::<LENGTH>();
4929+
&arr[from..to]
4930+
}
4931+
4932+
/// A mutable version of the previous function
4933+
pub fn any_slice_of_array_mut<T, const LENGTH: usize>(arr: &mut [T; LENGTH]) -> &mut [T] {
4934+
let (from, to) = any_range::<LENGTH>();
4935+
&mut arr[from..to]
4936+
}
4937+
4938+
fn any_range<const LENGTH: usize>() -> (usize, usize) {
4939+
let from: usize = kani::any();
4940+
let to: usize = kani::any();
4941+
kani::assume(to <= LENGTH);
4942+
kani::assume(from <= to);
4943+
(from, to)
4944+
}
4945+
4946+
#[kani::proof]
4947+
pub fn check_partition_dedup_by() {
4948+
const ARR_SIZE: usize = 1000;
4949+
let mut x: [u8; ARR_SIZE] = kani::any();
4950+
let xs = any_slice_of_array_mut(&mut x);
4951+
unsafe {
4952+
xs.partition_dedup_by(|a, b| a == b);
4953+
}
4954+
}
4955+
}

scripts/check_kani.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ cargo build-dev --release
4444
echo "Running tests..."
4545
echo
4646
cd "$VERIFY_RUST_STD_DIR"
47-
$KANI_DIR/scripts/kani verify-std -Z unstable-options $VERIFY_RUST_STD_DIR/library --target-dir "$RUNNER_TEMP" -Z function-contracts -Z mem-predicates
47+
$KANI_DIR/scripts/kani verify-std -Z unstable-options $VERIFY_RUST_STD_DIR/library --target-dir "$RUNNER_TEMP" -Z function-contracts -Z mem-predicates -Z loop-contracts
4848

4949
echo "Tests completed."
5050
echo

0 commit comments

Comments
 (0)