creusot_contracts/std/
ptr.rs1use crate::prelude::*;
2#[cfg(creusot)]
3use crate::std::mem::{align_of_logic, size_of_logic};
4use std::ptr::*;
5
6#[logic(opaque)]
10pub fn metadata_logic<T: ?Sized>(_: *const T) -> <T as Pointee>::Metadata {
11 dead
12}
13
14#[logic(open, inline)]
34#[intrinsic("metadata_matches")]
35pub fn metadata_matches<T: ?Sized>(_value: T, _metadata: <T as Pointee>::Metadata) -> bool {
36 dead
37}
38
39#[allow(unused)]
41#[logic]
42#[intrinsic("metadata_matches_slice")]
43fn metadata_matches_slice<T>(value: [T], len: usize) -> bool {
44 pearlite! { value@.len() == len@ }
45}
46
47#[allow(unused)]
49#[logic]
50#[intrinsic("metadata_matches_str")]
51fn metadata_matches_str(value: str, len: usize) -> bool {
52 pearlite! { value@.to_bytes().len() == len@ }
53}
54
55#[allow(unused_variables)]
67#[logic(open, inline)]
68#[intrinsic("is_aligned_logic")]
69pub fn is_aligned_logic<T: ?Sized>(ptr: *const T) -> bool {
70 dead
71}
72
73#[allow(unused)]
75#[logic]
76#[intrinsic("is_aligned_logic_sized")]
77fn is_aligned_logic_sized<T>(ptr: *const T) -> bool {
78 ptr.is_aligned_to_logic(align_of_logic::<T>())
79}
80
81#[allow(unused)]
83#[logic]
84#[intrinsic("is_aligned_logic_slice")]
85fn is_aligned_logic_slice<T>(ptr: *const [T]) -> bool {
86 ptr.is_aligned_to_logic(align_of_logic::<T>())
87}
88
89#[allow(dead_code)]
100pub struct PtrDeepModel {
101 pub addr: usize,
102 runtime_metadata: usize,
103}
104
105impl<T: ?Sized> DeepModel for *mut T {
106 type DeepModelTy = PtrDeepModel;
107 #[trusted]
108 #[logic(opaque)]
109 #[ensures(result.addr == self.addr_logic())]
110 fn deep_model(self) -> Self::DeepModelTy {
111 dead
112 }
113}
114
115impl<T: ?Sized> DeepModel for *const T {
116 type DeepModelTy = PtrDeepModel;
117 #[trusted]
118 #[logic(opaque)]
119 #[ensures(result.addr == self.addr_logic())]
120 fn deep_model(self) -> Self::DeepModelTy {
121 dead
122 }
123}
124
125pub trait PointerExt<T: ?Sized>: Sized {
126 #[logic]
128 fn addr_logic(self) -> usize;
129
130 #[logic(open, sealed)]
132 fn is_null_logic(self) -> bool {
133 self.addr_logic() == 0usize
134 }
135
136 #[logic(open, sealed)]
140 fn is_aligned_to_logic(self, align: usize) -> bool {
141 pearlite! { self.addr_logic() & (align - 1usize) == 0usize }
142 }
143
144 #[logic]
150 fn is_aligned_logic(self) -> bool;
151}
152
153impl<T: ?Sized> PointerExt<T> for *const T {
154 #[logic]
155 #[cfg_attr(target_pointer_width = "16", builtin("creusot.prelude.Ptr$BW$.addr_logic_u16"))]
156 #[cfg_attr(target_pointer_width = "32", builtin("creusot.prelude.Ptr$BW$.addr_logic_u32"))]
157 #[cfg_attr(target_pointer_width = "64", builtin("creusot.prelude.Ptr$BW$.addr_logic_u64"))]
158 fn addr_logic(self) -> usize {
159 dead
160 }
161
162 #[logic(open, inline)]
163 fn is_aligned_logic(self) -> bool {
164 is_aligned_logic(self)
165 }
166}
167
168impl<T: ?Sized> PointerExt<T> for *mut T {
169 #[logic]
170 #[cfg_attr(target_pointer_width = "16", builtin("creusot.prelude.Ptr$BW$.addr_logic_u16"))]
171 #[cfg_attr(target_pointer_width = "32", builtin("creusot.prelude.Ptr$BW$.addr_logic_u32"))]
172 #[cfg_attr(target_pointer_width = "64", builtin("creusot.prelude.Ptr$BW$.addr_logic_u64"))]
173 fn addr_logic(self) -> usize {
174 dead
175 }
176
177 #[logic(open, inline)]
178 fn is_aligned_logic(self) -> bool {
179 is_aligned_logic(self)
180 }
181}
182
183pub trait SizedPointerExt<T>: PointerExt<T> {
185 #[logic]
189 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() < usize::MAX@)]
190 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
191 fn offset_logic(self, offset: Int) -> Self;
192
193 #[logic(law)]
195 #[ensures(self.offset_logic(0) == self)]
196 fn offset_logic_zero(self);
197
198 #[logic(law)]
200 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
201 fn offset_logic_assoc(self, offset1: Int, offset2: Int);
202
203 #[logic]
207 fn sub_logic(self, rhs: Self) -> Int;
208
209 #[logic(law)]
210 #[ensures(self.sub_logic(self) == 0)]
211 fn sub_logic_refl(self);
212
213 #[logic(law)]
214 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
215 fn sub_offset_logic(self, offset: Int);
216}
217
218impl<T> SizedPointerExt<T> for *const T {
219 #[trusted]
220 #[logic(opaque)]
221 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() < usize::MAX@)]
222 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
223 fn offset_logic(self, offset: Int) -> Self {
224 dead
225 }
226
227 #[trusted]
228 #[logic(law)]
229 #[ensures(self.offset_logic(0) == self)]
230 fn offset_logic_zero(self) {}
231
232 #[trusted]
233 #[logic(law)]
234 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
235 fn offset_logic_assoc(self, offset1: Int, offset2: Int) {}
236
237 #[allow(unused)]
238 #[trusted]
239 #[logic(opaque)]
240 fn sub_logic(self, rhs: Self) -> Int {
241 dead
242 }
243
244 #[trusted]
245 #[logic(law)]
246 #[ensures(self.sub_logic(self) == 0)]
247 fn sub_logic_refl(self) {}
248
249 #[trusted]
250 #[logic(law)]
251 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
252 fn sub_offset_logic(self, offset: Int) {}
253}
254
255pub trait SlicePointerExt<T>: PointerExt<[T]> {
260 #[logic]
262 fn thin(self) -> *const T;
263
264 #[logic]
266 fn len_logic(self) -> usize;
267
268 #[logic(law)]
270 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
271 fn slice_ptr_ext(self, other: Self);
272}
273
274impl<T> SlicePointerExt<T> for *const [T] {
275 #[logic(open, inline)]
277 fn thin(self) -> *const T {
278 self as *const T
279 }
280
281 #[logic(open, inline)]
283 fn len_logic(self) -> usize {
284 pearlite! { metadata_logic(self) }
285 }
286
287 #[trusted]
289 #[logic(law)]
290 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
291 fn slice_ptr_ext(self, other: Self) {}
292}
293
294extern_spec! {
295 impl<T: ?Sized> *const T {
296 #[check(ghost)]
297 #[ensures(result == self.addr_logic())]
298 fn addr(self) -> usize;
299
300 #[check(ghost)]
301 #[ensures(result == self.is_null_logic())]
302 fn is_null(self) -> bool;
303
304 #[check(ghost)]
305 #[erasure]
306 #[ensures(result == self as _)]
307 fn cast<U>(self) -> *const U {
308 self as _
309 }
310
311 #[check(terminates)]
312 #[erasure]
313 #[ensures(result == self.is_aligned_logic())]
314 fn is_aligned(self) -> bool
315 where T: Sized,
316 {
317 self.is_aligned_to(std::mem::align_of::<T>())
318 }
319
320 #[check(ghost)]
321 #[erasure]
322 #[bitwise_proof]
323 #[requires(align != 0usize && align & (align - 1usize) == 0usize)]
324 #[ensures(result == self.is_aligned_to_logic(align))]
325 fn is_aligned_to(self, align: usize) -> bool
326 {
327 if !align.is_power_of_two() {
328 ::core::panic::panic_2021!("is_aligned_to: align is not a power-of-two");
329 }
330 self.addr() & (align - 1) == 0
331 }
332 }
333
334 impl<T: ?Sized> *mut T {
335 #[check(ghost)]
336 #[ensures(result == self.addr_logic())]
337 fn addr(self) -> usize;
338
339 #[check(ghost)]
340 #[ensures(result == self.is_null_logic())]
341 fn is_null(self) -> bool;
342
343 #[check(ghost)]
344 #[erasure]
345 #[ensures(result == self as _)]
346 fn cast<U>(self) -> *mut U {
347 self as _
348 }
349
350 #[check(terminates)]
351 #[erasure]
352 #[ensures(result == self.is_aligned_logic())]
353 fn is_aligned(self) -> bool
354 where T: Sized,
355 {
356 self.is_aligned_to(std::mem::align_of::<T>())
357 }
358
359 #[check(ghost)]
360 #[erasure]
361 #[bitwise_proof]
362 #[requires(align != 0usize && align & (align - 1usize) == 0usize)]
363 #[ensures(result == self.is_aligned_to_logic(align))]
364 fn is_aligned_to(self, align: usize) -> bool
365 {
366 if !align.is_power_of_two() {
367 ::core::panic::panic_2021!("is_aligned_to: align is not a power-of-two");
368 }
369 self.addr() & (align - 1) == 0
370 }
371 }
372
373 impl<T> *const [T] {
374 #[ensures(result == metadata_logic(self))]
375 fn len(self) -> usize;
376 }
377
378 impl<T> *mut [T] {
379 #[ensures(result == metadata_logic(self))]
380 fn len(self) -> usize;
381 }
382
383 mod std {
384 mod ptr {
385 #[check(ghost)]
386 #[ensures(result.is_null_logic())]
387 fn null<T>() -> *const T
388 where
389 T: std::ptr::Thin + ?Sized;
390
391 #[check(ghost)]
392 #[ensures(result.is_null_logic())]
393 fn null_mut<T>() -> *mut T
394 where
395 T: std::ptr::Thin + ?Sized;
396
397 #[check(ghost)]
398 #[ensures(result == (p.addr_logic() == q.addr_logic()))]
399 fn addr_eq<T, U>(p: *const T, q: *const U) -> bool
400 where
401 T: ?Sized, U: ?Sized;
402
403 #[check(ghost)]
404 #[ensures(result == metadata_logic(ptr))]
405 fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata;
406
407 #[check(ghost)]
410 #[ensures(false)]
411 unsafe fn read_volatile<T>(src: *const T) -> T;
412
413 #[ensures(result as *const T == data && result.len_logic() == len)]
414 fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T];
415
416 #[ensures(result as *mut T == data && result.len_logic() == len)]
417 fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T];
418 }
419 }
420
421 impl<T> Clone for *mut T {
422 #[check(ghost)]
423 #[ensures(result == *self)]
424 fn clone(&self) -> *mut T {
425 *self
426 }
427 }
428
429 impl<T> Clone for *const T {
430 #[check(ghost)]
431 #[ensures(result == *self)]
432 fn clone(&self) -> *const T {
433 *self
434 }
435 }
436}