Skip to content

Commit 1e5ba53

Browse files
committed
Add contracts for Layout and Alignment
These contracts seek to capture what is described in documentation and debug assertions.
1 parent 5d8ee62 commit 1e5ba53

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

library/core/src/alloc/layout.rs

+30
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
// collections, resulting in having to optimize down excess IR multiple times.
55
// Your performance intuition is useless. Run perf.
66

7+
use safety::requires;
78
use crate::cmp;
89
use crate::error::Error;
910
use crate::fmt;
1011
use crate::mem;
1112
use crate::ptr::{Alignment, NonNull};
1213

14+
#[cfg(kani)]
15+
use crate::kani;
16+
1317
// While this function is used in one place and its implementation
1418
// could be inlined, the previous attempts to do so made rustc
1519
// slower:
@@ -117,6 +121,9 @@ impl Layout {
117121
#[must_use]
118122
#[inline]
119123
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
124+
#[requires(align > 0)]
125+
#[requires((align & (align - 1)) == 0)]
126+
#[requires(size <= isize::MAX as usize - (align - 1))]
120127
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
121128
// SAFETY: the caller is required to uphold the preconditions.
122129
unsafe { Layout { size, align: Alignment::new_unchecked(align) } }
@@ -492,3 +499,26 @@ impl fmt::Display for LayoutError {
492499
f.write_str("invalid parameters to Layout::from_size_align")
493500
}
494501
}
502+
503+
#[cfg(kani)]
504+
#[unstable(feature="kani", issue="none")]
505+
mod verify {
506+
use super::*;
507+
508+
#[kani::proof_for_contract(Layout::from_size_align_unchecked)]
509+
pub fn check_from_size_align_unchecked() {
510+
let shift_index = kani::any::<usize>();
511+
kani::assume(shift_index < core::mem::size_of::<usize>() * 8);
512+
let a : usize = 1 << shift_index;
513+
kani::assume(a > 0);
514+
515+
let s = kani::any::<usize>();
516+
kani::assume(s <= isize::MAX as usize - (a - 1));
517+
518+
unsafe {
519+
let layout = Layout::from_size_align_unchecked(s, a);
520+
assert_eq!(layout.size(), s);
521+
assert_eq!(layout.align(), a);
522+
}
523+
}
524+
}

library/core/src/ptr/alignment.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
use safety::requires;
12
use crate::num::NonZero;
23
#[cfg(debug_assertions)]
34
use crate::ub_checks::assert_unsafe_precondition;
45
use crate::{cmp, fmt, hash, mem, num};
56

7+
#[cfg(kani)]
8+
use crate::kani;
9+
610
/// A type storing a `usize` which is a power of two, and thus
711
/// represents a possible alignment in the Rust abstract machine.
812
///
@@ -76,6 +80,8 @@ impl Alignment {
7680
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
7781
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
7882
#[inline]
83+
#[requires(align > 0)]
84+
#[requires((align & (align - 1)) == 0)]
7985
pub const unsafe fn new_unchecked(align: usize) -> Self {
8086
#[cfg(debug_assertions)]
8187
assert_unsafe_precondition!(

0 commit comments

Comments
 (0)