1mod nonnull;
2
3pub use self::nonnull::NonNullExt;
4#[cfg(creusot)]
5use crate::std::mem::{align_of_logic, size_of_logic, size_of_val_logic};
6use crate::{
7 ghost::{NotObjective, Perm, perm::PermTarget},
8 prelude::*,
9};
10use core::marker::PhantomData;
11#[cfg(creusot)]
12use core::ptr::Pointee;
13
14#[logic(opaque)]
18pub fn metadata_logic<T: ?Sized>(_: *const T) -> <T as Pointee>::Metadata {
19 dead
20}
21
22#[logic(open, inline)]
42#[intrinsic("metadata_matches")]
43pub fn metadata_matches<T: ?Sized>(_value: T, _metadata: <T as Pointee>::Metadata) -> bool {
44 dead
45}
46
47#[allow(unused)]
49#[logic]
50#[intrinsic("metadata_matches_slice")]
51fn metadata_matches_slice<T>(value: [T], len: usize) -> bool {
52 pearlite! { value@.len() == len@ }
53}
54
55#[allow(unused)]
57#[logic]
58#[intrinsic("metadata_matches_str")]
59fn metadata_matches_str(value: str, len: usize) -> bool {
60 pearlite! { value@.to_bytes().len() == len@ }
61}
62
63#[allow(unused_variables)]
75#[logic(open, inline)]
76#[intrinsic("is_aligned_logic")]
77pub fn is_aligned_logic<T: ?Sized>(ptr: *const T) -> bool {
78 dead
79}
80
81#[allow(unused)]
83#[logic]
84#[intrinsic("is_aligned_logic_sized")]
85fn is_aligned_logic_sized<T>(ptr: *const T) -> bool {
86 ptr.is_aligned_to_logic(align_of_logic::<T>())
87}
88
89#[allow(unused)]
91#[logic]
92#[intrinsic("is_aligned_logic_slice")]
93fn is_aligned_logic_slice<T>(ptr: *const [T]) -> bool {
94 ptr.is_aligned_to_logic(align_of_logic::<T>())
95}
96
97#[allow(dead_code)]
108pub struct PtrDeepModel {
109 pub addr: usize,
110 runtime_metadata: usize,
111}
112
113impl<T: ?Sized> DeepModel for *mut T {
114 type DeepModelTy = PtrDeepModel;
115 #[trusted]
116 #[logic(opaque)]
117 #[ensures(result.addr == self.addr_logic())]
118 fn deep_model(self) -> Self::DeepModelTy {
119 dead
120 }
121}
122
123impl<T: ?Sized> DeepModel for *const T {
124 type DeepModelTy = PtrDeepModel;
125 #[trusted]
126 #[logic(opaque)]
127 #[ensures(result.addr == self.addr_logic())]
128 fn deep_model(self) -> Self::DeepModelTy {
129 dead
130 }
131}
132
133pub trait PointerExt<T: ?Sized>: Sized {
135 #[logic]
137 fn addr_logic(self) -> usize;
138
139 #[logic(open, sealed)]
141 fn is_null_logic(self) -> bool {
142 self.addr_logic() == 0usize
143 }
144
145 #[logic(open, sealed)]
149 fn is_aligned_to_logic(self, align: usize) -> bool {
150 pearlite! { self.addr_logic() & (align - 1usize) == 0usize }
151 }
152
153 #[logic]
159 fn is_aligned_logic(self) -> bool;
160}
161
162impl<T: ?Sized> PointerExt<T> for *const T {
163 #[logic]
164 #[cfg_attr(target_pointer_width = "16", builtin("creusot.prelude.Ptr$BW$.addr_logic_u16"))]
165 #[cfg_attr(target_pointer_width = "32", builtin("creusot.prelude.Ptr$BW$.addr_logic_u32"))]
166 #[cfg_attr(target_pointer_width = "64", builtin("creusot.prelude.Ptr$BW$.addr_logic_u64"))]
167 fn addr_logic(self) -> usize {
168 dead
169 }
170
171 #[logic(open, inline)]
172 fn is_aligned_logic(self) -> bool {
173 is_aligned_logic(self)
174 }
175}
176
177impl<T: ?Sized> PointerExt<T> for *mut T {
178 #[logic]
179 #[cfg_attr(target_pointer_width = "16", builtin("creusot.prelude.Ptr$BW$.addr_logic_u16"))]
180 #[cfg_attr(target_pointer_width = "32", builtin("creusot.prelude.Ptr$BW$.addr_logic_u32"))]
181 #[cfg_attr(target_pointer_width = "64", builtin("creusot.prelude.Ptr$BW$.addr_logic_u64"))]
182 fn addr_logic(self) -> usize {
183 dead
184 }
185
186 #[logic(open, inline)]
187 fn is_aligned_logic(self) -> bool {
188 is_aligned_logic(self)
189 }
190}
191
192pub trait SizedPointerExt<T>: PointerExt<T> {
194 #[logic]
198 #[requires(0 <= self.addr_logic()@ + offset * size_of_logic::<T>())]
199 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() <= usize::MAX@)]
200 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
201 fn offset_logic(self, offset: Int) -> Self;
202
203 #[logic(law)]
205 #[ensures(self.offset_logic(0) == self)]
206 fn offset_logic_zero(self);
207
208 #[logic(law)]
210 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
211 fn offset_logic_assoc(self, offset1: Int, offset2: Int);
212
213 #[logic]
217 fn sub_logic(self, rhs: Self) -> Int;
218
219 #[logic(law)]
220 #[ensures(self.sub_logic(self) == 0)]
221 fn sub_logic_refl(self);
222
223 #[logic(law)]
224 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
225 #[ensures(self.sub_logic(self.offset_logic(offset)) == - offset)]
226 fn sub_offset_logic(self, offset: Int);
227}
228
229impl<T> SizedPointerExt<T> for *const T {
230 #[trusted]
231 #[logic(opaque)]
232 #[requires(0 <= self.addr_logic()@ + offset * size_of_logic::<T>())]
233 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() <= usize::MAX@)]
234 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
235 fn offset_logic(self, offset: Int) -> Self {
236 dead
237 }
238
239 #[trusted]
240 #[logic(law)]
241 #[ensures(self.offset_logic(0) == self)]
242 fn offset_logic_zero(self) {}
243
244 #[trusted]
245 #[logic(law)]
246 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
247 fn offset_logic_assoc(self, offset1: Int, offset2: Int) {}
248
249 #[allow(unused)]
250 #[trusted]
251 #[logic(opaque)]
252 fn sub_logic(self, rhs: Self) -> Int {
253 dead
254 }
255
256 #[trusted]
257 #[logic(law)]
258 #[ensures(self.sub_logic(self) == 0)]
259 fn sub_logic_refl(self) {}
260
261 #[trusted]
262 #[logic(law)]
263 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
264 #[ensures(self.sub_logic(self.offset_logic(offset)) == - offset)]
265 fn sub_offset_logic(self, offset: Int) {}
266}
267
268impl<T> SizedPointerExt<T> for *mut T {
270 #[logic(open, inline)]
271 #[requires(0 <= self.addr_logic()@ + offset * size_of_logic::<T>())]
272 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() <= usize::MAX@)]
273 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
274 fn offset_logic(self, offset: Int) -> Self {
275 pearlite! { (self as *const T).offset_logic(offset) as *mut T }
276 }
277
278 #[logic(law)]
279 #[ensures(self.offset_logic(0) == self)]
280 fn offset_logic_zero(self) {}
281
282 #[logic(law)]
283 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
284 fn offset_logic_assoc(self, offset1: Int, offset2: Int) {}
285
286 #[logic(open, inline)]
287 fn sub_logic(self, rhs: Self) -> Int {
288 pearlite! { (self as *const T).sub_logic(rhs as *const T) }
289 }
290
291 #[logic(law)]
292 #[ensures(self.sub_logic(self) == 0)]
293 fn sub_logic_refl(self) {}
294
295 #[logic(law)]
296 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
297 #[ensures(self.sub_logic(self.offset_logic(offset)) == - offset)]
298 fn sub_offset_logic(self, offset: Int) {}
299}
300
301pub trait SlicePointerExt<T>: PointerExt<[T]> {
306 #[logic]
308 fn thin(self) -> *const T;
309
310 #[logic]
312 fn len_logic(self) -> usize;
313
314 #[logic(law)]
316 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
317 fn slice_ptr_ext(self, other: Self);
318}
319
320impl<T> SlicePointerExt<T> for *const [T] {
321 #[logic(open, inline)]
323 fn thin(self) -> *const T {
324 self as *const T
325 }
326
327 #[logic(open, inline)]
329 fn len_logic(self) -> usize {
330 pearlite! { metadata_logic(self) }
331 }
332
333 #[trusted]
335 #[logic(law)]
336 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
337 fn slice_ptr_ext(self, other: Self) {}
338}
339
340impl<T> SlicePointerExt<T> for *mut [T] {
341 #[logic(open, inline)]
343 fn thin(self) -> *const T {
344 self as *const T
345 }
346
347 #[logic(open, inline)]
349 fn len_logic(self) -> usize {
350 pearlite! { metadata_logic(self as *const [T]) }
351 }
352
353 #[logic(law)]
355 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
356 fn slice_ptr_ext(self, other: Self) {
357 (self as *const [T]).slice_ptr_ext(other as *const [T])
358 }
359}
360
361extern_spec! {
362 impl<T: ?Sized> *const T {
363 #[check(ghost)]
364 #[ensures(result == self.addr_logic())]
365 fn addr(self) -> usize;
366
367 #[check(ghost)]
368 #[ensures(result == self.is_null_logic())]
369 fn is_null(self) -> bool;
370
371 #[check(ghost)]
372 #[erasure]
373 #[ensures(result == self as _)]
374 fn cast<U>(self) -> *const U {
375 self as _
376 }
377
378 #[check(ghost)]
379 #[erasure]
380 #[ensures(result == self as _)]
381 const fn cast_mut(self) -> *mut T {
382 self as _
383 }
384
385 #[check(terminates)]
386 #[erasure]
387 #[ensures(result == self.is_aligned_logic())]
388 fn is_aligned(self) -> bool
389 where T: Sized,
390 {
391 self.is_aligned_to(core::mem::align_of::<T>())
392 }
393
394 #[check(ghost)]
395 #[erasure]
396 #[bitwise_proof]
397 #[requires(align != 0usize && align & (align - 1usize) == 0usize)]
398 #[ensures(result == self.is_aligned_to_logic(align))]
399 fn is_aligned_to(self, align: usize) -> bool
400 {
401 if !align.is_power_of_two() {
402 ::core::panic::panic_2021!("is_aligned_to: align is not a power-of-two");
403 }
404 self.addr() & (align - 1) == 0
405 }
406 }
407
408 impl<T: ?Sized> *mut T {
409 #[check(ghost)]
410 #[ensures(result == self.addr_logic())]
411 fn addr(self) -> usize;
412
413 #[check(ghost)]
414 #[ensures(result == self.is_null_logic())]
415 fn is_null(self) -> bool;
416
417 #[check(ghost)]
418 #[erasure]
419 #[ensures(result == self as _)]
420 fn cast<U>(self) -> *mut U {
421 self as _
422 }
423
424 #[check(ghost)]
425 #[erasure]
426 #[ensures(result == self as _)]
427 fn cast_const(self) -> *const T {
428 self as _
429 }
430
431 #[check(terminates)]
432 #[erasure]
433 #[ensures(result == self.is_aligned_logic())]
434 fn is_aligned(self) -> bool
435 where T: Sized,
436 {
437 self.is_aligned_to(core::mem::align_of::<T>())
438 }
439
440 #[check(ghost)]
441 #[erasure]
442 #[bitwise_proof]
443 #[requires(align != 0usize && align & (align - 1usize) == 0usize)]
444 #[ensures(result == self.is_aligned_to_logic(align))]
445 fn is_aligned_to(self, align: usize) -> bool
446 {
447 if !align.is_power_of_two() {
448 ::core::panic::panic_2021!("is_aligned_to: align is not a power-of-two");
449 }
450 self.addr() & (align - 1) == 0
451 }
452 }
453
454 impl<T> *const [T] {
455 #[ensures(result == metadata_logic(self))]
456 fn len(self) -> usize;
457 }
458
459 impl<T> *mut [T] {
460 #[ensures(result == metadata_logic(self))]
461 fn len(self) -> usize;
462 }
463
464 mod core {
465 mod ptr {
466 #[check(ghost)]
467 #[ensures(result.is_null_logic())]
468 fn null<T: core::ptr::Thin + ?Sized>() -> *const T;
469
470 #[check(ghost)]
471 #[ensures(result.is_null_logic())]
472 fn null_mut<T: core::ptr::Thin + ?Sized>() -> *mut T;
473
474 #[check(ghost)]
475 #[ensures(result == (p.addr_logic() == q.addr_logic()))]
476 fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool;
477
478 #[check(ghost)]
479 #[ensures(result == metadata_logic(ptr))]
480 fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata;
481
482 #[check(ghost)]
485 #[ensures(false)]
486 unsafe fn read_volatile<T>(src: *const T) -> T;
487
488 #[ensures(result as *const T == data && result.len_logic() == len)]
489 fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T];
490
491 #[ensures(result as *mut T == data && result.len_logic() == len)]
492 fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T];
493 }
494 }
495
496 impl<T> Clone for *mut T {
497 #[check(ghost)]
498 #[ensures(result == *self)]
499 fn clone(&self) -> *mut T {
500 *self
501 }
502 }
503
504 impl<T> Clone for *const T {
505 #[check(ghost)]
506 #[ensures(result == *self)]
507 fn clone(&self) -> *const T {
508 *self
509 }
510 }
511}
512
513impl<T: ?Sized> PermTarget for *const T {
514 type Value<'a>
515 = &'a T
516 where
517 Self: 'a;
518 type PermPayload = (NotObjective, PhantomData<T>, [bool]);
519
520 #[logic(open, inline)]
525 fn is_disjoint(&self, self_val: &T, other: &Self, other_val: &T) -> bool {
526 pearlite! {
527 size_of_val_logic(*self_val) != 0 && size_of_val_logic(*other_val) != 0 ==>
528 self.addr_logic() != other.addr_logic()
529 }
530 }
531}
532
533impl<T: ?Sized> Invariant for Perm<*const T> {
534 #[logic(open, prophetic)]
535 fn invariant(self) -> bool {
536 pearlite! {
537 !self.ward().is_null_logic()
538 && metadata_matches(*self.val(), metadata_logic(*self.ward()))
539 && inv(self.val())
540 }
541 }
542}
543
544impl<T: ?Sized> Perm<*const T> {
545 #[check(terminates)] #[ensures(*result.1.ward() == result.0 && *result.1.val() == v)]
549 #[cfg(feature = "std")]
550 pub fn new(v: T) -> (*mut T, Ghost<Box<Perm<*const T>>>)
551 where
552 T: Sized,
553 {
554 Self::from_box(Box::new(v))
555 }
556
557 #[trusted]
559 #[check(terminates)] #[ensures(*result.1.ward() == result.0 && *result.1.val() == *val)]
561 #[erasure(Box::into_raw)]
562 #[cfg(feature = "std")]
563 pub fn from_box(val: Box<T>) -> (*mut T, Ghost<Box<Perm<*const T>>>) {
564 (Box::into_raw(val), Ghost::conjure())
565 }
566
567 #[trusted]
579 #[check(terminates)] #[ensures(*result.1.ward() == result.0)]
581 #[ensures(*result.1.val() == *r)]
582 #[intrinsic("perm_from_ref")]
583 pub fn from_ref(r: &T) -> (*const T, Ghost<&Perm<*const T>>) {
584 (r, Ghost::conjure())
585 }
586
587 #[trusted]
599 #[check(terminates)] #[ensures(*result.1.ward() == result.0)]
601 #[ensures(*result.1.val() == *r)]
602 #[ensures(*(^result.1.inner_logic()).val() == ^r)]
603 #[intrinsic("perm_from_mut")]
604 pub fn from_mut(r: &mut T) -> (*mut T, Ghost<&mut Perm<*const T>>) {
605 (r, Ghost::conjure())
606 }
607
608 #[trusted]
627 #[check(terminates)]
628 #[requires(ptr == *own.ward())]
629 #[ensures(*result == *own.val())]
630 #[allow(unused_variables)]
631 #[intrinsic("perm_as_ref")]
632 pub unsafe fn as_ref(ptr: *const T, own: Ghost<&Perm<*const T>>) -> &T {
633 unsafe { &*ptr }
634 }
635
636 #[trusted]
655 #[check(terminates)]
656 #[allow(unused_variables)]
657 #[requires(ptr as *const T == *own.ward())]
658 #[ensures(*result == *own.val())]
659 #[ensures((^own).ward() == own.ward())]
660 #[ensures(*(^own).val() == ^result)]
661 #[intrinsic("perm_as_mut")]
662 pub unsafe fn as_mut(ptr: *mut T, own: Ghost<&mut Perm<*const T>>) -> &mut T {
663 unsafe { &mut *ptr }
664 }
665
666 #[trusted]
675 #[check(terminates)]
676 #[requires(ptr as *const T == *own.ward())]
677 #[ensures(*result == *own.val())]
678 #[allow(unused_variables)]
679 #[erasure(Box::from_raw)]
680 #[cfg(feature = "std")]
681 pub unsafe fn to_box(ptr: *mut T, own: Ghost<Box<Perm<*const T>>>) -> Box<T> {
682 unsafe { Box::from_raw(ptr) }
683 }
684
685 #[check(terminates)]
694 #[requires(ptr as *const T == *own.ward())]
695 #[cfg(feature = "std")]
696 pub unsafe fn drop(ptr: *mut T, own: Ghost<Box<Perm<*const T>>>) {
697 let _ = unsafe { Self::to_box(ptr, own) };
698 }
699}
700
701impl<T> Perm<*const [T]> {
709 #[logic(open, inline)]
711 pub fn len(self) -> Int {
712 pearlite! { self.val()@.len() }
713 }
714
715 #[trusted]
717 #[check(ghost)]
718 #[requires(0 <= index && index <= self.len())]
719 #[ensures(self.ward().thin() == result.0.ward().thin())]
720 #[ensures(self.ward().thin().offset_logic(index) == result.1.ward().thin())]
721 #[ensures(self.val()@[..index] == result.0.val()@)]
722 #[ensures(self.val()@[index..] == result.1.val()@)]
723 pub fn split_at(&self, index: Int) -> (&Self, &Self) {
724 let _ = index;
725 panic!("called ghost function in normal code")
726 }
727
728 #[trusted]
730 #[check(ghost)]
731 #[requires(0 <= index && index <= self.len())]
732 #[ensures(self.ward().thin() == result.0.ward().thin())]
733 #[ensures(self.ward().thin().offset_logic(index) == result.1.ward().thin())]
734 #[ensures(self.val()@[..index] == result.0.val()@)]
735 #[ensures(self.val()@[index..] == result.1.val()@)]
736 #[ensures((^self).ward() == self.ward())]
737 #[ensures((^result.0).val()@.len() == index)]
738 #[ensures((^self).val()@ == (^result.0).val()@.concat((^result.1).val()@))]
739 pub fn split_at_mut(&mut self, index: Int) -> (&mut Perm<*const [T]>, &mut Perm<*const [T]>) {
740 let _ = index;
741 panic!("called ghost function in normal code")
742 }
743
744 #[trusted]
746 #[check(ghost)]
747 #[ensures(result.len() == self.len())]
748 #[ensures(forall<i> 0 <= i && i < self.len()
749 ==> *result[i].ward() == self.ward().thin().offset_logic(i)
750 && *result[i].val() == self.val()@[i])]
751 pub fn elements(&self) -> Seq<&Perm<*const T>> {
752 panic!("called ghost function in normal code")
753 }
754
755 #[trusted]
757 #[check(ghost)]
758 #[ensures(result.len() == self.len())]
759 #[ensures(forall<i> 0 <= i && i < self.len()
760 ==> *result[i].ward() == self.ward().thin().offset_logic(i)
761 && *result[i].val() == self.val()@[i])]
762 #[ensures((^self).ward() == self.ward())]
763 #[ensures(forall<i> 0 <= i && i < self.len() ==> *(^result[i]).val() == (^self).val()@[i])]
764 pub fn elements_mut(&mut self) -> Seq<&mut Perm<*const T>> {
765 panic!("called ghost function in normal code")
766 }
767
768 #[check(ghost)]
770 #[requires(0 <= index && index < self.len())]
771 #[ensures(*result.ward() == self.ward().thin().offset_logic(index))]
772 #[ensures(*result.val() == self.val()@[index])]
773 pub fn index(&self, index: Int) -> &Perm<*const T> {
774 let mut r = self.elements();
775 r.split_off_ghost(index).pop_front_ghost().unwrap()
776 }
777
778 #[check(ghost)]
780 #[requires(0 <= index && index < self.len())]
781 #[ensures(*result.ward() == self.ward().thin().offset_logic(index))]
782 #[ensures(*result.val() == self.val()@[index])]
783 #[ensures((^self).ward() == self.ward())]
784 #[ensures(*(^result).val() == (^self).val()@[index])]
785 #[ensures(forall<k: Int> 0 <= k && k < self.len() && k != index ==> (^self).val()@[k] == self.val()@[k])]
786 pub fn index_mut(&mut self, index: Int) -> &mut Perm<*const T> {
787 let mut r = self.elements_mut();
788 proof_assert! { forall<k> index < k && k < r.len() ==> r[k].val() == r[index..].tail()[k-index-1].val() };
789 let _r = snapshot! { r };
790 let result = r.split_off_ghost(index).pop_front_ghost().unwrap();
791 proof_assert! { forall<i> 0 <= i && i < index ==> r[i] == _r[i] }; result
793 }
794
795 #[trusted]
797 #[check(ghost)]
798 #[ensures(result.ward() == self.ward().thin())]
799 #[ensures(result.len()@ == self.len())]
800 pub fn live(&self) -> PtrLive<'_, T> {
801 panic!("called ghost function in normal code")
802 }
803
804 #[trusted]
806 #[check(ghost)]
807 #[ensures(result.ward() == self.ward().thin())]
808 #[ensures(result.len()@ == self.len())]
809 pub fn live_mut<'a, 'b>(self: &'b &'a mut Self) -> PtrLive<'a, T> {
810 panic!("called ghost function in normal code")
811 }
812}
813
814#[opaque]
822pub struct PtrLive<'a, T>(PhantomData<&'a T>);
823
824impl<T> Clone for PtrLive<'_, T> {
825 #[trusted]
826 #[check(ghost)]
827 #[ensures(result == *self)]
828 fn clone(&self) -> Self {
829 panic!("called ghost function in normal code")
830 }
831}
832
833impl<T> Copy for PtrLive<'_, T> {}
834
835impl<T> Invariant for PtrLive<'_, T> {
836 #[logic(open, prophetic)]
837 fn invariant(self) -> bool {
838 pearlite! {
839 self.len()@ * size_of_logic::<T>() <= isize::MAX@
842 && self.ward().addr_logic()@ + self.len()@ * size_of_logic::<T>() <= usize::MAX@
846 && self.ward().is_aligned_logic()
848 }
849 }
850}
851
852impl<T> PtrLive<'_, T> {
853 #[trusted]
855 #[logic(opaque)]
856 pub fn ward(self) -> *const T {
857 dead
858 }
859
860 #[trusted]
864 #[logic(opaque)]
865 pub fn len(self) -> usize {
866 dead
867 }
868
869 #[logic(open, inline)]
878 pub fn contains_range(self, ptr: *const T, len: Int) -> bool {
879 pearlite! {
880 let offset = ptr.sub_logic(self.ward());
881 ptr == self.ward().offset_logic(offset)
883 && 0 <= offset && offset <= self.len()@
884 && 0 <= offset + len && offset + len <= self.len()@
885 }
886 }
887}
888
889pub trait PtrAddExt<'a, T> {
910 #[requires(false)]
912 unsafe fn add_live(self, offset: usize, live: Ghost<PtrLive<'a, T>>) -> Self;
913
914 #[requires(false)]
916 unsafe fn offset_live(self, offset: isize, live: Ghost<PtrLive<'a, T>>) -> Self;
917}
918
919impl<'a, T> PtrAddExt<'a, T> for *const T {
920 #[trusted]
922 #[erasure(<*const T>::add)]
923 #[requires(live.contains_range(self, offset@))]
924 #[ensures(result == self.offset_logic(offset@))]
925 unsafe fn add_live(self, offset: usize, live: Ghost<PtrLive<'a, T>>) -> Self {
926 let _ = live;
927 unsafe { self.add(offset) }
928 }
929
930 #[trusted]
932 #[erasure(<*const T>::offset)]
933 #[requires(live.contains_range(self, offset@))]
934 #[ensures(result == self.offset_logic(offset@))]
935 unsafe fn offset_live(self, offset: isize, live: Ghost<PtrLive<'a, T>>) -> Self {
936 let _ = live;
937 unsafe { self.offset(offset) }
938 }
939}
940
941impl<'a, T> PtrAddExt<'a, T> for *mut T {
942 #[trusted]
944 #[erasure(<*mut T>::add)]
945 #[requires(live.contains_range(self, offset@))]
946 #[ensures(result == self.offset_logic(offset@))]
947 unsafe fn add_live(self, offset: usize, live: Ghost<PtrLive<'a, T>>) -> Self {
948 let _ = live;
949 unsafe { self.add(offset) }
950 }
951
952 #[trusted]
954 #[erasure(<*mut T>::offset)]
955 #[requires(live.contains_range(self, offset@))]
956 #[ensures(result == self.offset_logic(offset@))]
957 unsafe fn offset_live(self, offset: isize, live: Ghost<PtrLive<'a, T>>) -> Self {
958 let _ = live;
959 unsafe { self.offset(offset) }
960 }
961}