creusot_contracts/std/mem.rs
1use crate::prelude::*;
2use std::mem::*;
3
4extern_spec! {
5 mod std {
6 mod mem {
7 #[check(ghost)]
8 #[ensures(^dest == src)]
9 #[ensures(result == *dest)]
10 fn replace<T>(dest: &mut T, src: T) -> T {
11 let mut src = src;
12 swap(dest, &mut src);
13 src
14 }
15
16 #[check(ghost)]
17 #[ensures(^x == *y)]
18 #[ensures(^y == *x)]
19 fn swap<T>(x: &mut T, y: &mut T);
20
21 #[ensures(result == *dest)]
22 #[ensures(T::default.postcondition((), ^dest))]
23 fn take<T: Default>(dest: &mut T) -> T {
24 replace(dest, T::default())
25 }
26
27 #[check(ghost)]
28 #[ensures(resolve(t))]
29 fn drop<T>(t: T) {}
30
31 #[check(ghost)]
32 #[ensures(resolve(t))]
33 fn forget<T>(t: T) {}
34
35 // This is not `#[check(ghost)]` because `size_of` overflows are only caught at codegen time
36 // which ghost code doesn't reach.
37 #[check(terminates)]
38 #[ensures(result@ == size_of_logic::<T>())]
39 fn size_of<T>() -> usize;
40
41 // This is not `#[check(ghost)]` because `size_of_val` overflows are only caught at codegen time
42 // which ghost code doesn't reach.
43 #[check(terminates)]
44 #[ensures(result@ == size_of_val_logic::<T>(*val))]
45 fn size_of_val<T: ?Sized>(val: &T) -> usize;
46
47 // This is not `#[check(ghost)]` because `align_of` overflows are only caught at codegen time
48 // which ghost code doesn't reach.
49 //
50 // Alignment values may range from 1 to 2^29
51 // ([source](https://doc.rust-lang.org/reference/type-layout.html#r-layout.repr.alignment.constraint-alignment)),
52 // which may overflow on 16-bit archs.
53 #[check(terminates)]
54 #[ensures(result == align_of_logic::<T>())]
55 fn align_of<T>() -> usize;
56 }
57 }
58}
59
60/// [`size_of`] as a logic `Int` value.
61///
62/// The definition of `size_of_logic` guarantees at least the following,
63/// based on the documentation of [`size_of`]:
64///
65/// - `()`, `bool`, `char`, primitive integers and floats are known constants.
66/// - For `T: Sized`, the pointer and reference types `*const T`, `*mut T`,
67/// `&T`, `&mut T`, `Box<T>`, `Option<&T>`, `Option<&mut T>`, and
68/// `Option<Box<T>>` have the same size as `usize`.
69/// - `[T; N]` has size `N * size_of_logic::<T>()`.
70///
71/// `size_of_logic` for `repr(C)` types is not yet implemented.
72///
73/// See also [the Rust Reference section on Type Layout][RRTL].
74///
75/// Note that the value of `size_of`/`size_of_logic` may depend on the version of rustc, notably
76/// for ADTs with the default representation `repr(Rust)`.
77///
78/// [`size_of`]: https://doc.rust-lang.org/std/mem/fn.size_of.html
79/// [RRTL]: https://doc.rust-lang.org/stable/reference/type-layout.html
80#[trusted]
81#[logic(open, inline)]
82#[intrinsic("size_of_logic")]
83#[ensures(0 <= result)]
84pub fn size_of_logic<T>() -> Int {
85 dead
86}
87
88/// [`size_of_val`] as a logic `Int` value.
89#[trusted]
90#[logic(open, inline)]
91#[intrinsic("size_of_val_logic")]
92#[ensures(0 <= result)]
93pub fn size_of_val_logic<T: ?Sized>(val: T) -> Int {
94 dead
95}
96
97#[allow(unused)]
98#[logic]
99#[intrinsic("size_of_val_logic_sized")]
100fn size_of_val_logic_sized<T>(_val: T) -> Int {
101 size_of_logic::<T>()
102}
103
104#[allow(unused)]
105#[logic]
106#[intrinsic("size_of_val_logic_slice")]
107fn size_of_val_logic_slice<T>(val: [T]) -> Int {
108 pearlite! { size_of_logic::<T>() * val@.len() }
109}
110
111#[allow(unused)]
112#[logic]
113#[intrinsic("size_of_val_logic_str")]
114fn size_of_val_logic_str(val: str) -> Int {
115 pearlite! { val@.to_bytes().len() }
116}
117
118/// [`align_of`] as a logic `Int` value.
119///
120/// [`align_of`]: https://doc.rust-lang.org/std/mem/fn.align_of.html
121#[trusted]
122#[logic(open, inline)]
123#[intrinsic("align_of_logic")]
124#[ensures(0usize != result && result & (result - 1usize) == 0usize)]
125#[ensures(size_of_logic::<T>() % result@ == 0)]
126pub fn align_of_logic<T>() -> usize {
127 dead
128}