Skip to content

Commit e795a44

Browse files
committed
Add harnesses for all Alignment public functions
1 parent 25c9cca commit e795a44

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

library/core/src/ptr/alignment.rs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use safety::requires;
1+
use safety::{ensures, requires};
22
use crate::num::NonZero;
33
#[cfg(debug_assertions)]
44
use crate::ub_checks::assert_unsafe_precondition;
@@ -60,6 +60,7 @@ impl Alignment {
6060
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
6161
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
6262
#[inline]
63+
#[ensures(|result| align.is_power_of_two() == result.is_some())]
6364
pub const fn new(align: usize) -> Option<Self> {
6465
if align.is_power_of_two() {
6566
// SAFETY: Just checked it only has one bit set
@@ -81,6 +82,8 @@ impl Alignment {
8182
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
8283
#[inline]
8384
#[requires(align > 0 && (align & (align - 1)) == 0)]
85+
#[ensures(|result| result.as_usize() == align)]
86+
#[ensures(|result| result.as_usize().is_power_of_two())]
8487
pub const unsafe fn new_unchecked(align: usize) -> Self {
8588
#[cfg(debug_assertions)]
8689
assert_unsafe_precondition!(
@@ -98,6 +101,7 @@ impl Alignment {
98101
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
99102
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
100103
#[inline]
104+
#[ensures(|result| result.is_power_of_two())]
101105
pub const fn as_usize(self) -> usize {
102106
self.0 as usize
103107
}
@@ -106,6 +110,7 @@ impl Alignment {
106110
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
107111
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
108112
#[inline]
113+
#[ensures(|result| result.get().is_power_of_two())]
109114
pub const fn as_nonzero(self) -> NonZero<usize> {
110115
// SAFETY: All the discriminants are non-zero.
111116
unsafe { NonZero::new_unchecked(self.as_usize()) }
@@ -127,6 +132,7 @@ impl Alignment {
127132
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
128133
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
129134
#[inline]
135+
#[ensures(|result| (*result as usize) < mem::size_of::<usize>() * 8)]
130136
pub const fn log2(self) -> u32 {
131137
self.as_nonzero().trailing_zeros()
132138
}
@@ -157,6 +163,7 @@ impl Alignment {
157163
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
158164
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
159165
#[inline]
166+
#[ensures(|result| *result > 0)]
160167
pub const fn mask(self) -> usize {
161168
// SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
162169
!(unsafe { self.as_usize().unchecked_sub(1) })
@@ -375,14 +382,68 @@ enum AlignmentEnum {
375382
mod verify {
376383
use super::*;
377384

385+
// pub const fn of<T>() -> Self
386+
#[kani::proof]
387+
pub fn check_of_i32() {
388+
let alignment = Alignment::of::<i32>();
389+
assert!(alignment.as_usize().is_power_of_two());
390+
}
391+
392+
// pub const fn new(align: usize) -> Option<Self>
393+
#[kani::proof_for_contract(Alignment::new)]
394+
pub fn check_new() {
395+
let a = kani::any::<usize>();
396+
let alignment_opt = Alignment::new(a);
397+
match alignment_opt {
398+
Some(alignment) => assert_eq!(alignment.as_usize(), a),
399+
None => assert!(!a.is_power_of_two())
400+
}
401+
}
402+
403+
// pub const unsafe fn new_unchecked(align: usize) -> Self
378404
#[kani::proof_for_contract(Alignment::new_unchecked)]
379405
pub fn check_new_unchecked() {
380406
let a = kani::any::<usize>();
381407

382408
unsafe {
383409
let alignment = Alignment::new_unchecked(a);
410+
assert!(alignment.as_usize() > 0);
411+
}
412+
}
413+
414+
// pub const fn as_usize(self) -> usize
415+
#[kani::proof_for_contract(Alignment::as_usize)]
416+
pub fn check_as_usize() {
417+
let a = kani::any::<usize>();
418+
if let Some(alignment) = Alignment::new(a) {
384419
assert_eq!(alignment.as_usize(), a);
385-
assert!(a.is_power_of_two());
420+
}
421+
}
422+
423+
// pub const fn as_nonzero(self) -> NonZero<usize>
424+
#[kani::proof_for_contract(Alignment::as_nonzero)]
425+
pub fn check_as_nonzero() {
426+
let a = kani::any::<usize>();
427+
if let Some(alignment) = Alignment::new(a) {
428+
assert_eq!(alignment.as_nonzero().get(), a);
429+
}
430+
}
431+
432+
// pub const fn log2(self) -> u32
433+
#[kani::proof_for_contract(Alignment::log2)]
434+
pub fn check_log2() {
435+
let a = kani::any::<usize>();
436+
if let Some(alignment) = Alignment::new(a) {
437+
assert_eq!(1usize << alignment.log2(), a);
438+
}
439+
}
440+
441+
// pub const fn mask(self) -> usize
442+
#[kani::proof_for_contract(Alignment::mask)]
443+
pub fn check_mask() {
444+
let a = kani::any::<usize>();
445+
if let Some(alignment) = Alignment::new(a) {
446+
assert_eq!(a & alignment.mask(), a);
386447
}
387448
}
388449
}

0 commit comments

Comments
 (0)