Skip to content

Commit 8e6b212

Browse files
committed
Add safety preconditions to alloc/src/collections/binary_heap/mod.rs
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.
1 parent 3a967e3 commit 8e6b212

File tree

1 file changed

+43
-0
lines changed
  • library/alloc/src/collections/binary_heap

1 file changed

+43
-0
lines changed

library/alloc/src/collections/binary_heap/mod.rs

+43
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@
143143
#![allow(missing_docs)]
144144
#![stable(feature = "rust1", since = "1.0.0")]
145145

146+
use safety::requires;
147+
#[cfg(kani)]
148+
#[unstable(feature="kani", issue="none")]
149+
use core::kani;
150+
146151
use core::alloc::Allocator;
147152
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen};
148153
use core::mem::{self, swap, ManuallyDrop};
@@ -672,6 +677,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
672677
/// # Safety
673678
///
674679
/// The caller must guarantee that `pos < self.len()`.
680+
#[requires(pos < self.len())]
675681
unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize {
676682
// Take out the value at `pos` and create a hole.
677683
// SAFETY: The caller guarantees that pos < self.len()
@@ -701,6 +707,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
701707
/// # Safety
702708
///
703709
/// The caller must guarantee that `pos < end <= self.len()`.
710+
#[requires(pos < end && end <= self.len())]
704711
unsafe fn sift_down_range(&mut self, pos: usize, end: usize) {
705712
// SAFETY: The caller guarantees that pos < end <= self.len().
706713
let mut hole = unsafe { Hole::new(&mut self.data, pos) };
@@ -741,6 +748,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
741748
/// # Safety
742749
///
743750
/// The caller must guarantee that `pos < self.len()`.
751+
#[requires(pos < self.len())]
744752
unsafe fn sift_down(&mut self, pos: usize) {
745753
let len = self.len();
746754
// SAFETY: pos < len is guaranteed by the caller and
@@ -757,6 +765,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
757765
/// # Safety
758766
///
759767
/// The caller must guarantee that `pos < self.len()`.
768+
#[requires(pos < self.len())]
760769
unsafe fn sift_down_to_bottom(&mut self, mut pos: usize) {
761770
let end = self.len();
762771
let start = pos;
@@ -1897,3 +1906,37 @@ impl<'a, T: 'a + Ord + Copy, A: Allocator> Extend<&'a T> for BinaryHeap<T, A> {
18971906
self.reserve(additional);
18981907
}
18991908
}
1909+
1910+
#[cfg(kani)]
1911+
#[unstable(feature="kani", issue="none")]
1912+
mod verify {
1913+
use super::*;
1914+
1915+
// unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize
1916+
#[kani::proof_for_contract(impl<T::sift_up)]
1917+
pub fn check_sift_up() {
1918+
let obj : impl<T = kani::any();
1919+
let _ = obj.sift_up(kani::any(), kani::any());
1920+
}
1921+
1922+
// unsafe fn sift_down_range(&mut self, pos: usize, end: usize)
1923+
#[kani::proof_for_contract(impl<T::sift_down_range)]
1924+
pub fn check_sift_down_range() {
1925+
let obj : impl<T = kani::any();
1926+
let _ = obj.sift_down_range(kani::any(), kani::any());
1927+
}
1928+
1929+
// unsafe fn sift_down(&mut self, pos: usize)
1930+
#[kani::proof_for_contract(impl<T::sift_down)]
1931+
pub fn check_sift_down() {
1932+
let obj : impl<T = kani::any();
1933+
let _ = obj.sift_down(kani::any());
1934+
}
1935+
1936+
// unsafe fn sift_down_to_bottom(&mut self, mut pos: usize)
1937+
#[kani::proof_for_contract(impl<T::sift_down_to_bottom)]
1938+
pub fn check_sift_down_to_bottom() {
1939+
let obj : impl<T = kani::any();
1940+
let _ = obj.sift_down_to_bottom(kani::any());
1941+
}
1942+
}

0 commit comments

Comments
 (0)