Skip to content

Commit

Permalink
Add contracts for Layout and Alignment
Browse files Browse the repository at this point in the history
These contracts seek to capture what is described in documentation and
debug assertions.
  • Loading branch information
tautschnig committed Jul 10, 2024
1 parent 5d8ee62 commit 1e5ba53
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
30 changes: 30 additions & 0 deletions library/core/src/alloc/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
// collections, resulting in having to optimize down excess IR multiple times.
// Your performance intuition is useless. Run perf.

use safety::requires;
use crate::cmp;
use crate::error::Error;
use crate::fmt;
use crate::mem;
use crate::ptr::{Alignment, NonNull};

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

// While this function is used in one place and its implementation
// could be inlined, the previous attempts to do so made rustc
// slower:
Expand Down Expand Up @@ -117,6 +121,9 @@ impl Layout {
#[must_use]
#[inline]
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
#[requires(align > 0)]
#[requires((align & (align - 1)) == 0)]
#[requires(size <= isize::MAX as usize - (align - 1))]
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
// SAFETY: the caller is required to uphold the preconditions.
unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
Expand Down Expand Up @@ -492,3 +499,26 @@ impl fmt::Display for LayoutError {
f.write_str("invalid parameters to Layout::from_size_align")
}
}

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

#[kani::proof_for_contract(Layout::from_size_align_unchecked)]
pub fn check_from_size_align_unchecked() {
let shift_index = kani::any::<usize>();
kani::assume(shift_index < core::mem::size_of::<usize>() * 8);
let a : usize = 1 << shift_index;
kani::assume(a > 0);

let s = kani::any::<usize>();
kani::assume(s <= isize::MAX as usize - (a - 1));

unsafe {
let layout = Layout::from_size_align_unchecked(s, a);
assert_eq!(layout.size(), s);
assert_eq!(layout.align(), a);
}
}
}
6 changes: 6 additions & 0 deletions library/core/src/ptr/alignment.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use safety::requires;
use crate::num::NonZero;
#[cfg(debug_assertions)]
use crate::ub_checks::assert_unsafe_precondition;
use crate::{cmp, fmt, hash, mem, num};

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

/// A type storing a `usize` which is a power of two, and thus
/// represents a possible alignment in the Rust abstract machine.
///
Expand Down Expand Up @@ -76,6 +80,8 @@ impl Alignment {
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
#[requires(align > 0)]
#[requires((align & (align - 1)) == 0)]
pub const unsafe fn new_unchecked(align: usize) -> Self {
#[cfg(debug_assertions)]
assert_unsafe_precondition!(
Expand Down

0 comments on commit 1e5ba53

Please sign in to comment.