1
- use safety:: requires;
1
+ use safety:: { ensures , requires} ;
2
2
use crate :: num:: NonZero ;
3
3
#[ cfg( debug_assertions) ]
4
4
use crate :: ub_checks:: assert_unsafe_precondition;
@@ -48,6 +48,8 @@ impl Alignment {
48
48
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
49
49
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
50
50
#[ inline]
51
+ #[ requires( mem:: align_of:: <T >( ) . is_power_of_two( ) ) ]
52
+ #[ ensures( |result| result. as_usize( ) . is_power_of_two( ) ) ]
51
53
pub const fn of < T > ( ) -> Self {
52
54
// SAFETY: rustc ensures that type alignment is always a power of two.
53
55
unsafe { Alignment :: new_unchecked ( mem:: align_of :: < T > ( ) ) }
@@ -60,6 +62,8 @@ impl Alignment {
60
62
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
61
63
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
62
64
#[ inline]
65
+ #[ ensures( |result| align. is_power_of_two( ) == result. is_some( ) ) ]
66
+ #[ ensures( |result| result. is_none( ) || result. unwrap( ) . as_usize( ) == align) ]
63
67
pub const fn new ( align : usize ) -> Option < Self > {
64
68
if align. is_power_of_two ( ) {
65
69
// SAFETY: Just checked it only has one bit set
@@ -80,8 +84,9 @@ impl Alignment {
80
84
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
81
85
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
82
86
#[ 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( ) ) ]
85
90
pub const unsafe fn new_unchecked ( align : usize ) -> Self {
86
91
#[ cfg( debug_assertions) ]
87
92
assert_unsafe_precondition ! (
@@ -99,6 +104,7 @@ impl Alignment {
99
104
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
100
105
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
101
106
#[ inline]
107
+ #[ ensures( |result| result. is_power_of_two( ) ) ]
102
108
pub const fn as_usize ( self ) -> usize {
103
109
self . 0 as usize
104
110
}
@@ -107,6 +113,8 @@ impl Alignment {
107
113
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
108
114
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
109
115
#[ inline]
116
+ #[ ensures( |result| result. get( ) . is_power_of_two( ) ) ]
117
+ #[ ensures( |result| result. get( ) == self . as_usize( ) ) ]
110
118
pub const fn as_nonzero ( self ) -> NonZero < usize > {
111
119
// SAFETY: All the discriminants are non-zero.
112
120
unsafe { NonZero :: new_unchecked ( self . as_usize ( ) ) }
@@ -128,6 +136,9 @@ impl Alignment {
128
136
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
129
137
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
130
138
#[ 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( ) ) ]
131
142
pub const fn log2 ( self ) -> u32 {
132
143
self . as_nonzero ( ) . trailing_zeros ( )
133
144
}
@@ -158,6 +169,9 @@ impl Alignment {
158
169
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
159
170
#[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
160
171
#[ inline]
172
+ #[ ensures( |result| * result > 0 ) ]
173
+ #[ ensures( |result| * result == !( self . as_usize( ) -1 ) ) ]
174
+ #[ ensures( |result| self . as_usize( ) & * result == self . as_usize( ) ) ]
161
175
pub const fn mask ( self ) -> usize {
162
176
// SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
163
177
!( unsafe { self . as_usize ( ) . unchecked_sub ( 1 ) } )
@@ -370,3 +384,68 @@ enum AlignmentEnum {
370
384
_Align1Shl62 = 1 << 62 ,
371
385
_Align1Shl63 = 1 << 63 ,
372
386
}
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