1#![allow(unused_imports)]
2
3use super::arithmetic::power::*;
4use super::arithmetic::power2::*;
5use super::bits::*;
6use super::math::*;
7use super::prelude::*;
8use core::mem::MaybeUninit;
9
10verus! {
11
12pub open spec fn valid_layout(size: usize, align: usize) -> bool {
14 is_pow2(align as int) && size <= isize::MAX as int - (isize::MAX as int % align as int)
15}
16
17#[cfg_attr(not(verus_verify_core), deprecated = "is_sized is now defunct; lemmas that require V to be sized should now use the trait bound `V: Sized` instead of is_sized<V>")]
18pub uninterp spec fn is_sized<V: ?Sized>() -> bool;
19
20pub uninterp spec fn size_of<V>() -> nat;
21
22pub uninterp spec fn align_of<V>() -> nat;
23
24pub uninterp spec fn spec_size_of_val<V: ?Sized>(val: &V) -> nat;
27
28pub uninterp spec fn spec_align_of_val<V: ?Sized>(val: &V) -> nat;
30
31#[verifier::inline]
45pub open spec fn size_of_as_usize<V>() -> usize
46 recommends
47 size_of::<V>() as usize as int == size_of::<V>(),
48{
49 size_of::<V>() as usize
50}
51
52#[verifier::inline]
53pub open spec fn align_of_as_usize<V>() -> usize
54 recommends
55 align_of::<V>() as usize as int == align_of::<V>(),
56{
57 align_of::<V>() as usize
58}
59
60#[verifier::inline]
61pub open spec fn size_of_val_as_usize<V: ?Sized>(val: &V) -> usize
62 recommends
63 spec_size_of_val::<V>(val) as usize as int == spec_size_of_val::<V>(val),
64{
65 spec_size_of_val::<V>(val) as usize
66}
67
68#[verifier::inline]
69pub open spec fn align_of_val_as_usize<V: ?Sized>(val: &V) -> usize
70 recommends
71 spec_align_of_val::<V>(val) as usize as int == spec_align_of_val::<V>(val),
72{
73 spec_align_of_val::<V>(val) as usize
74}
75
76#[verifier::when_used_as_spec(size_of_as_usize)]
77pub assume_specification<V>[ core::mem::size_of::<V> ]() -> (u: usize)
78 ensures
79 u as nat == size_of::<V>(),
80 opens_invariants none
81 no_unwind
82;
83
84#[verifier::when_used_as_spec(align_of_as_usize)]
85pub assume_specification<V>[ core::mem::align_of::<V> ]() -> (u: usize)
86 ensures
87 u as nat == align_of::<V>(),
88 opens_invariants none
89 no_unwind
90;
91
92#[verifier::when_used_as_spec(size_of_val_as_usize)]
93pub assume_specification<V: ?Sized>[ core::mem::size_of_val::<V> ](val: &V) -> (u: usize)
94 ensures
95 u as nat == spec_size_of_val::<V>(val),
96 opens_invariants none
97 no_unwind
98;
99
100#[verifier::when_used_as_spec(align_of_val_as_usize)]
101pub assume_specification<V: ?Sized>[ core::mem::align_of_val::<V> ](val: &V) -> (u: usize)
102 ensures
103 u as nat == spec_align_of_val::<V>(val),
104 opens_invariants none
105 no_unwind
106;
107
108#[verifier::external_body]
117#[inline(always)]
118pub const exec fn layout_for_type_is_valid<V>()
119 ensures
120 valid_layout(size_of::<V>() as usize, align_of::<V>() as usize),
121 size_of::<V>() as usize as nat == size_of::<V>(),
122 align_of::<V>() as usize as nat == align_of::<V>(),
123 align_of::<V>() != 0,
124 size_of::<V>() % align_of::<V>() == 0,
125 opens_invariants none
126 no_unwind
127{
128}
129
130#[allow(unused_variables)]
139#[verifier::external_body]
140#[inline(always)]
141pub const exec fn layout_for_val_is_valid<V: ?Sized>(val: Tracked<&V>)
142 ensures
143 valid_layout(spec_size_of_val::<V>(val@) as usize, spec_align_of_val::<V>(val@) as usize),
144 spec_size_of_val::<V>(val@) as usize as nat == spec_size_of_val::<V>(val@),
145 spec_align_of_val::<V>(val@) as usize as nat == spec_align_of_val::<V>(val@),
146 spec_align_of_val::<V>(val@) != 0,
147 spec_size_of_val::<V>(val@) % spec_align_of_val::<V>(val@) == 0,
148 opens_invariants none
149 no_unwind
150{
151}
152
153pub broadcast axiom fn layout_of_primitives()
158 ensures
159 #![trigger size_of::<bool>()]
160 #![trigger size_of::<char>()]
161 #![trigger size_of::<u8>()]
162 #![trigger size_of::<i8>()]
163 #![trigger size_of::<u16>()]
164 #![trigger size_of::<i16>()]
165 #![trigger size_of::<u32>()]
166 #![trigger size_of::<i32>()]
167 #![trigger size_of::<u64>()]
168 #![trigger size_of::<i64>()]
169 #![trigger size_of::<usize>()]
170 #![trigger size_of::<isize>()]
171 size_of::<bool>() == 1,
172 size_of::<char>() == 4,
173 size_of::<u8>() == size_of::<i8>() == 1,
174 size_of::<u16>() == size_of::<i16>() == 2,
175 size_of::<u32>() == size_of::<i32>() == 4,
176 size_of::<u64>() == size_of::<i64>() == 8,
177 size_of::<u128>() == size_of::<i128>() == 16,
178 size_of::<usize>() == size_of::<isize>(),
179 size_of::<usize>() * 8 == usize::BITS,
180;
181
182pub broadcast axiom fn layout_of_unit_tuple()
184 ensures
185 #![trigger size_of::<()>()]
186 #![trigger align_of::<()>()]
187 size_of::<()>() == 0,
188 align_of::<()>() == 1,
189;
190
191pub broadcast axiom fn layout_of_references_and_pointers<T: ?Sized>()
193 ensures
194 #![trigger size_of::<*mut T>()]
195 #![trigger size_of::<*const T>()]
196 #![trigger size_of::<&T>()]
197 #![trigger align_of::<*mut T>()]
198 #![trigger align_of::<*const T>()]
199 #![trigger align_of::<&T>()]
200 size_of::<*mut T>() == size_of::<*const T>() == size_of::<&T>(),
201 align_of::<*mut T>() == align_of::<*const T>() == align_of::<&T>(),
202;
203
204pub broadcast axiom fn layout_of_references_and_pointers_for_sized_types<T: Sized>()
207 ensures
208 #![trigger size_of::<*mut T>()]
209 #![trigger align_of::<*mut T>()]
210 size_of::<*mut T>() == size_of::<usize>(),
211 align_of::<*mut T>() == align_of::<usize>(),
212;
213
214pub broadcast axiom fn layout_of_references_and_pointers_for_unsized_types<T: ?Sized>()
217 ensures
218 #![trigger size_of::<*mut T>()]
219 #![trigger align_of::<*mut T>()]
220 size_of::<*mut T>() >= size_of::<usize>(),
221 align_of::<*mut T>() >= align_of::<usize>(),
222;
223
224pub broadcast axiom fn layout_of_slices<T>(x: &[T])
227 ensures
228 #![trigger spec_size_of_val::<[T]>(x)]
229 #![trigger spec_align_of_val::<[T]>(x)]
230 spec_align_of_val::<[T]>(x) == align_of::<T>(),
231 spec_size_of_val::<[T]>(x) == x@.len() * size_of::<T>(),
232;
233
234pub broadcast axiom fn layout_of_str(x: &str)
237 ensures
238 #![trigger spec_align_of_val::<str>(x)]
239 #![trigger spec_size_of_val::<str>(x)]
240 spec_align_of_val::<str>(x) == align_of::<u8>(),
242;
243
244pub broadcast axiom fn align_properties<T>()
247 ensures
248 #![trigger align_of::<T>()]
249 size_of::<T>() % align_of::<T>() == 0,
250 is_pow2(align_of::<T>() as int),
251;
252
253pub broadcast proof fn align_nonzero<T>()
256 ensures
257 #![trigger align_of::<T>()]
258 align_of::<T>() > 0,
259{
260 broadcast use crate::vstd::arithmetic::power::lemma_pow_positive, align_properties;
261 broadcast use crate::vstd::arithmetic::power2::is_pow2_equiv;
262
263}
264
265pub broadcast proof fn align_of_u8()
269 ensures
270 #![trigger align_of::<u8>()]
271 align_of::<u8>() == 1,
272{
273 broadcast use {
274 layout_of_primitives,
275 align_properties,
276 align_nonzero,
277 crate::vstd::arithmetic::div_mod::lemma_mod_is_zero,
278 };
279
280}
281
282pub proof fn usize_size_pow2()
285 ensures
286 is_pow2(size_of::<usize>() as int),
287{
288 broadcast use super::group_vstd_default;
289
290 reveal(is_pow2);
291
292 assert(is_pow2(4)) by (compute);
293 assert(is_pow2(8)) by (compute);
294}
295
296pub proof fn unsigned_int_max_values()
298 ensures
299 (usize::MAX as nat) == pow2(usize::BITS as nat) - 1,
300 (usize::MAX as nat) == pow(256, size_of::<usize>()) - 1,
301 (u8::MAX as nat) == pow2(u8::BITS as nat) - 1,
302 (u8::MAX as nat) == pow(256, size_of::<u8>()) - 1,
303 (u16::MAX as nat) == pow2(u16::BITS as nat) - 1,
304 (u16::MAX as nat) == pow(256, size_of::<u16>()) - 1,
305 (u32::MAX as nat) == pow2(u32::BITS as nat) - 1,
306 (u32::MAX as nat) == pow(256, size_of::<u32>()) - 1,
307 (u64::MAX as nat) == pow2(u64::BITS as nat) - 1,
308 (u64::MAX as nat) == pow(256, size_of::<u64>()) - 1,
309 (u128::MAX as nat) == pow2(u128::BITS as nat) - 1,
310 (u128::MAX as nat) == pow(256, size_of::<u128>()) - 1,
311{
312 broadcast use layout_of_primitives;
313
314 reveal(pow);
315 assert(0x100 == pow2(8)) by (compute);
316 assert(0x1_0000 == pow2(16)) by (compute);
317 assert(0x1_0000_0000 == pow2(32)) by (compute);
318 assert(0x1_0000_0000_0000_0000 == pow2(64)) by (compute);
319 assert(0x1_0000_0000_0000_0000_0000_0000_0000_0000 == pow2(128)) by (compute);
320 assert(pow(256, 1) == pow2(8)) by (compute);
321 assert(pow(256, 2) == pow2(16)) by (compute);
322 assert(pow(256, 4) == pow2(32)) by (compute);
323 assert(pow(256, 8) == pow2(64)) by (compute);
324 assert(pow(256, 16) == pow2(128)) by (compute);
325}
326
327pub proof fn signed_int_min_max_values()
329 ensures
330 (isize::MAX as nat) == pow2((isize::BITS - 1) as nat) - 1,
331 abs(isize::MIN as int) == pow2((isize::BITS - 1) as nat),
332 (isize::MAX as nat) * 2 == pow(256, size_of::<isize>()) - 2,
333 abs(isize::MIN as int) * 2 == pow(256, size_of::<isize>()),
334 (i8::MAX as nat) == pow2((i8::BITS - 1) as nat) - 1,
335 abs(i8::MIN as int) == pow2((i8::BITS - 1) as nat),
336 (i8::MAX as nat) * 2 == pow(256, size_of::<i8>()) - 2,
337 abs(i8::MIN as int) * 2 == pow(256, size_of::<i8>()),
338 (i16::MAX as nat) == pow2((i16::BITS - 1) as nat) - 1,
339 abs(i16::MIN as int) == pow2((i16::BITS - 1) as nat),
340 (i16::MAX as nat) * 2 == pow(256, size_of::<i16>()) - 2,
341 abs(i16::MIN as int) * 2 == pow(256, size_of::<i16>()),
342 (i32::MAX as nat) == pow2((i32::BITS - 1) as nat) - 1,
343 abs(i32::MIN as int) == pow2((i32::BITS - 1) as nat),
344 (i32::MAX as nat) * 2 == pow(256, size_of::<i32>()) - 2,
345 abs(i32::MIN as int) * 2 == pow(256, size_of::<i32>()),
346 (i64::MAX as nat) == pow2((i64::BITS - 1) as nat) - 1,
347 abs(i64::MIN as int) == pow2((i64::BITS - 1) as nat),
348 (i64::MAX as nat) * 2 == pow(256, size_of::<i64>()) - 2,
349 abs(i64::MIN as int) * 2 == pow(256, size_of::<i64>()),
350 (i128::MAX as nat) == pow2((i128::BITS - 1) as nat) - 1,
351 abs(i128::MIN as int) == pow2((i128::BITS - 1) as nat),
352 (i128::MAX as nat) * 2 == pow(256, size_of::<i128>()) - 2,
353 abs(i128::MIN as int) * 2 == pow(256, size_of::<i128>()),
354{
355 broadcast use layout_of_primitives;
356
357 reveal(pow);
358 assert(0x80 == pow2(7)) by (compute);
359 assert(0x8_000 == pow2(15)) by (compute);
360 assert(0x80_000_000 == pow2(31)) by (compute);
361 assert(0x8_000_000_000_000_000 == pow2(63)) by (compute);
362 assert(0x80_000_000_000_000_000_000_000_000_000_000 == pow2(127)) by (compute);
363 assert(pow(256, 1) == pow2(7) * 2) by (compute);
364 assert(pow(256, 2) == pow2(15) * 2) by (compute);
365 assert(pow(256, 4) == pow2(31) * 2) by (compute);
366 assert(pow(256, 8) == pow2(63) * 2) by (compute);
367 assert(pow(256, 16) == pow2(127) * 2) by (compute);
368}
369
370pub broadcast group group_align_properties {
371 align_properties,
372 align_nonzero,
373}
374
375pub broadcast axiom fn layout_of_maybe_uninit<T: Sized>()
378 ensures
379 #![trigger size_of::<MaybeUninit<T>>()]
380 #![trigger align_of::<MaybeUninit<T>>()]
381 size_of::<MaybeUninit<T>>() == size_of::<T>(),
382 align_of::<MaybeUninit<T>>() == align_of::<T>(),
383;
384
385pub broadcast group group_layout_axioms {
386 layout_of_primitives,
387 layout_of_unit_tuple,
388 layout_of_references_and_pointers,
389 layout_of_references_and_pointers_for_sized_types,
390 layout_of_references_and_pointers_for_unsized_types,
391 layout_of_slices,
392 layout_of_str,
393 layout_of_maybe_uninit,
394 group_align_properties,
395}
396
397}