Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add harnesses for all functions in Alignment #42

Merged
merged 15 commits into from
Aug 20, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 80 additions & 3 deletions library/core/src/ptr/alignment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use safety::requires;
use safety::{ensures, requires};
use crate::num::NonZero;
#[cfg(debug_assertions)]
use crate::ub_checks::assert_unsafe_precondition;
Expand Down Expand Up @@ -60,6 +60,7 @@ impl Alignment {
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
#[ensures(|result| align.is_power_of_two() == result.is_some())]
pub const fn new(align: usize) -> Option<Self> {
if align.is_power_of_two() {
// SAFETY: Just checked it only has one bit set
Expand All @@ -80,8 +81,9 @@ 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)]
#[requires(align > 0 && (align & (align - 1)) == 0)]
#[ensures(|result| result.as_usize() == align)]
#[ensures(|result| result.as_usize().is_power_of_two())]
pub const unsafe fn new_unchecked(align: usize) -> Self {
#[cfg(debug_assertions)]
assert_unsafe_precondition!(
Expand All @@ -99,6 +101,7 @@ impl Alignment {
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
#[ensures(|result| result.is_power_of_two())]
pub const fn as_usize(self) -> usize {
self.0 as usize
}
Expand All @@ -107,6 +110,7 @@ impl Alignment {
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
#[ensures(|result| result.get().is_power_of_two())]
pub const fn as_nonzero(self) -> NonZero<usize> {
// SAFETY: All the discriminants are non-zero.
unsafe { NonZero::new_unchecked(self.as_usize()) }
Expand All @@ -128,6 +132,7 @@ impl Alignment {
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
#[ensures(|result| (*result as usize) < mem::size_of::<usize>() * 8)]
pub const fn log2(self) -> u32 {
tautschnig marked this conversation as resolved.
Show resolved Hide resolved
self.as_nonzero().trailing_zeros()
}
Expand Down Expand Up @@ -158,6 +163,7 @@ impl Alignment {
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
#[ensures(|result| *result > 0)]
pub const fn mask(self) -> usize {
tautschnig marked this conversation as resolved.
Show resolved Hide resolved
// SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
!(unsafe { self.as_usize().unchecked_sub(1) })
Expand Down Expand Up @@ -370,3 +376,74 @@ enum AlignmentEnum {
_Align1Shl62 = 1 << 62,
_Align1Shl63 = 1 << 63,
}

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

// pub const fn of<T>() -> Self
#[kani::proof]
pub fn check_of_i32() {
let alignment = Alignment::of::<i32>();
assert!(alignment.as_usize().is_power_of_two());
tautschnig marked this conversation as resolved.
Show resolved Hide resolved
}

// pub const fn new(align: usize) -> Option<Self>
#[kani::proof_for_contract(Alignment::new)]
pub fn check_new() {
let a = kani::any::<usize>();
let alignment_opt = Alignment::new(a);
match alignment_opt {
Some(alignment) => assert_eq!(alignment.as_usize(), a),
None => assert!(!a.is_power_of_two())
}
}
feliperodri marked this conversation as resolved.
Show resolved Hide resolved

// pub const unsafe fn new_unchecked(align: usize) -> Self
#[kani::proof_for_contract(Alignment::new_unchecked)]
pub fn check_new_unchecked() {
let a = kani::any::<usize>();

unsafe {
let alignment = Alignment::new_unchecked(a);
assert!(alignment.as_usize() > 0);
}
}

// pub const fn as_usize(self) -> usize
#[kani::proof_for_contract(Alignment::as_usize)]
pub fn check_as_usize() {
let a = kani::any::<usize>();
if let Some(alignment) = Alignment::new(a) {
assert_eq!(alignment.as_usize(), a);
celinval marked this conversation as resolved.
Show resolved Hide resolved
}
}

// pub const fn as_nonzero(self) -> NonZero<usize>
#[kani::proof_for_contract(Alignment::as_nonzero)]
pub fn check_as_nonzero() {
let a = kani::any::<usize>();
if let Some(alignment) = Alignment::new(a) {
assert_eq!(alignment.as_nonzero().get(), a);
}
}

// pub const fn log2(self) -> u32
#[kani::proof_for_contract(Alignment::log2)]
pub fn check_log2() {
let a = kani::any::<usize>();
if let Some(alignment) = Alignment::new(a) {
assert_eq!(1usize << alignment.log2(), a);
}
}

// pub const fn mask(self) -> usize
#[kani::proof_for_contract(Alignment::mask)]
pub fn check_mask() {
let a = kani::any::<usize>();
if let Some(alignment) = Alignment::new(a) {
assert_eq!(a & alignment.mask(), a);
}
}
}
Loading