1- use safety:: requires;
1+ use safety:: { ensures , requires} ;
22use crate :: num:: NonZero ;
33#[ cfg( debug_assertions) ]
44use crate :: ub_checks:: assert_unsafe_precondition;
@@ -48,6 +48,8 @@ impl Alignment {
4848 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
4949 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
5050 #[ inline]
51+ #[ requires( mem:: align_of:: <T >( ) . is_power_of_two( ) ) ]
52+ #[ ensures( |result| result. as_usize( ) . is_power_of_two( ) ) ]
5153 pub const fn of < T > ( ) -> Self {
5254 // SAFETY: rustc ensures that type alignment is always a power of two.
5355 unsafe { Alignment :: new_unchecked ( mem:: align_of :: < T > ( ) ) }
@@ -60,6 +62,8 @@ impl Alignment {
6062 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
6163 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
6264 #[ inline]
65+ #[ ensures( |result| align. is_power_of_two( ) == result. is_some( ) ) ]
66+ #[ ensures( |result| result. is_none( ) || result. unwrap( ) . as_usize( ) == align) ]
6367 pub const fn new ( align : usize ) -> Option < Self > {
6468 if align. is_power_of_two ( ) {
6569 // SAFETY: Just checked it only has one bit set
@@ -80,8 +84,9 @@ impl Alignment {
8084 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
8185 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
8286 #[ inline]
83- #[ requires( align > 0 ) ]
84- #[ requires( ( align & ( align - 1 ) ) == 0 ) ]
87+ #[ requires( align > 0 && ( align & ( align - 1 ) ) == 0 ) ]
88+ #[ ensures( |result| result. as_usize( ) == align) ]
89+ #[ ensures( |result| result. as_usize( ) . is_power_of_two( ) ) ]
8590 pub const unsafe fn new_unchecked ( align : usize ) -> Self {
8691 #[ cfg( debug_assertions) ]
8792 assert_unsafe_precondition ! (
@@ -99,6 +104,7 @@ impl Alignment {
99104 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
100105 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
101106 #[ inline]
107+ #[ ensures( |result| result. is_power_of_two( ) ) ]
102108 pub const fn as_usize ( self ) -> usize {
103109 self . 0 as usize
104110 }
@@ -107,6 +113,8 @@ impl Alignment {
107113 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
108114 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
109115 #[ inline]
116+ #[ ensures( |result| result. get( ) . is_power_of_two( ) ) ]
117+ #[ ensures( |result| result. get( ) == self . as_usize( ) ) ]
110118 pub const fn as_nonzero ( self ) -> NonZero < usize > {
111119 // SAFETY: All the discriminants are non-zero.
112120 unsafe { NonZero :: new_unchecked ( self . as_usize ( ) ) }
@@ -128,6 +136,9 @@ impl Alignment {
128136 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
129137 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
130138 #[ inline]
139+ #[ requires( self . as_usize( ) . is_power_of_two( ) ) ]
140+ #[ ensures( |result| ( * result as usize ) < mem:: size_of:: <usize >( ) * 8 ) ]
141+ #[ ensures( |result| 1usize << * result == self . as_usize( ) ) ]
131142 pub const fn log2 ( self ) -> u32 {
132143 self . as_nonzero ( ) . trailing_zeros ( )
133144 }
@@ -158,6 +169,9 @@ impl Alignment {
158169 #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
159170 #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
160171 #[ inline]
172+ #[ ensures( |result| * result > 0 ) ]
173+ #[ ensures( |result| * result == !( self . as_usize( ) -1 ) ) ]
174+ #[ ensures( |result| self . as_usize( ) & * result == self . as_usize( ) ) ]
161175 pub const fn mask ( self ) -> usize {
162176 // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
163177 !( unsafe { self . as_usize ( ) . unchecked_sub ( 1 ) } )
@@ -370,3 +384,68 @@ enum AlignmentEnum {
370384 _Align1Shl62 = 1 << 62 ,
371385 _Align1Shl63 = 1 << 63 ,
372386}
387+
388+ #[ cfg( kani) ]
389+ #[ unstable( feature="kani" , issue="none" ) ]
390+ mod verify {
391+ use super :: * ;
392+
393+ impl kani:: Arbitrary for Alignment {
394+ fn any ( ) -> Self {
395+ let align = kani:: any_where ( |a : & usize | a. is_power_of_two ( ) ) ;
396+ unsafe { mem:: transmute :: < usize , Alignment > ( align) }
397+ }
398+ }
399+
400+ // pub const fn of<T>() -> Self
401+ #[ kani:: proof_for_contract( Alignment :: of) ]
402+ pub fn check_of_i32 ( ) {
403+ let _ = Alignment :: of :: < i32 > ( ) ;
404+ }
405+
406+ // pub const fn new(align: usize) -> Option<Self>
407+ #[ kani:: proof_for_contract( Alignment :: new) ]
408+ pub fn check_new ( ) {
409+ let a = kani:: any :: < usize > ( ) ;
410+ let _ = Alignment :: new ( a) ;
411+ }
412+
413+ // pub const unsafe fn new_unchecked(align: usize) -> Self
414+ #[ kani:: proof_for_contract( Alignment :: new_unchecked) ]
415+ pub fn check_new_unchecked ( ) {
416+ let a = kani:: any :: < usize > ( ) ;
417+ unsafe {
418+ let _ = Alignment :: new_unchecked ( a) ;
419+ }
420+ }
421+
422+ // pub const fn as_usize(self) -> usize
423+ #[ kani:: proof_for_contract( Alignment :: as_usize) ]
424+ pub fn check_as_usize ( ) {
425+ let a = kani:: any :: < usize > ( ) ;
426+ if let Some ( alignment) = Alignment :: new ( a) {
427+ assert_eq ! ( alignment. as_usize( ) , a) ;
428+ }
429+ }
430+
431+ // pub const fn as_nonzero(self) -> NonZero<usize>
432+ #[ kani:: proof_for_contract( Alignment :: as_nonzero) ]
433+ pub fn check_as_nonzero ( ) {
434+ let alignment = kani:: any :: < Alignment > ( ) ;
435+ let _ = alignment. as_nonzero ( ) ;
436+ }
437+
438+ // pub const fn log2(self) -> u32
439+ #[ kani:: proof_for_contract( Alignment :: log2) ]
440+ pub fn check_log2 ( ) {
441+ let alignment = kani:: any :: < Alignment > ( ) ;
442+ let _ = alignment. log2 ( ) ;
443+ }
444+
445+ // pub const fn mask(self) -> usize
446+ #[ kani:: proof_for_contract( Alignment :: mask) ]
447+ pub fn check_mask ( ) {
448+ let alignment = kani:: any :: < Alignment > ( ) ;
449+ let _ = alignment. mask ( ) ;
450+ }
451+ }
0 commit comments