Skip to content

Commit

Permalink
Add safety preconditions to alloc/src/collections/binary_heap/mod.rs
Browse files Browse the repository at this point in the history
This diff adds `#[requires(...)]` attributes to the unsafe functions, translating the "SAFETY:" comments into code contracts. These contracts specify the preconditions that must be met for the function to be safely called.
  • Loading branch information
tautschnig committed Oct 17, 2024
1 parent dc862c4 commit 29b2c87
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions library/alloc/src/collections/binary_heap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@
#![allow(missing_docs)]
#![stable(feature = "rust1", since = "1.0.0")]

use safety::requires;
#[cfg(kani)]
use crate::kani;

use core::alloc::Allocator;
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen};
use core::mem::{self, swap, ManuallyDrop};
Expand Down Expand Up @@ -672,6 +676,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
/// # Safety
///
/// The caller must guarantee that `pos < self.len()`.
#[requires(pos < self.len())]
unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize {
// Take out the value at `pos` and create a hole.
// SAFETY: The caller guarantees that pos < self.len()
Expand Down Expand Up @@ -701,6 +706,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
/// # Safety
///
/// The caller must guarantee that `pos < end <= self.len()`.
#[requires(pos < end && end <= self.len())]
unsafe fn sift_down_range(&mut self, pos: usize, end: usize) {
// SAFETY: The caller guarantees that pos < end <= self.len().
let mut hole = unsafe { Hole::new(&mut self.data, pos) };
Expand Down Expand Up @@ -741,6 +747,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
/// # Safety
///
/// The caller must guarantee that `pos < self.len()`.
#[requires(pos < self.len())]
unsafe fn sift_down(&mut self, pos: usize) {
let len = self.len();
// SAFETY: pos < len is guaranteed by the caller and
Expand All @@ -757,6 +764,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
/// # Safety
///
/// The caller must guarantee that `pos < self.len()`.
#[requires(pos < self.len())]
unsafe fn sift_down_to_bottom(&mut self, mut pos: usize) {
let end = self.len();
let start = pos;
Expand Down Expand Up @@ -1897,3 +1905,37 @@ impl<'a, T: 'a + Ord + Copy, A: Allocator> Extend<&'a T> for BinaryHeap<T, A> {
self.reserve(additional);
}
}

#[cfg(kani)]
#[unstable(feature="kani", issue="none")]
mod verify {
use super::*;

// unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize
#[kani::proof_for_contract(impl<T::sift_up)]
pub fn check_sift_up() {
let obj : impl<T = kani::any();
let _ = obj.sift_up(kani::any());
}

// unsafe fn sift_down_range(&mut self, pos: usize, end: usize)
#[kani::proof_for_contract(impl<T::sift_down_range)]
pub fn check_sift_down_range() {
let obj : impl<T = kani::any();
let _ = obj.sift_down_range(kani::any());
}

// unsafe fn sift_down(&mut self, pos: usize)
#[kani::proof_for_contract(impl<T::sift_down)]
pub fn check_sift_down() {
let obj : impl<T = kani::any();
let _ = obj.sift_down(kani::any());
}

// unsafe fn sift_down_to_bottom(&mut self, mut pos: usize)
#[kani::proof_for_contract(impl<T::sift_down_to_bottom)]
pub fn check_sift_down_to_bottom() {
let obj : impl<T = kani::any();
let _ = obj.sift_down_to_bottom(kani::any());
}
}

0 comments on commit 29b2c87

Please sign in to comment.