1#[cfg(creusot)]
2use crate::std::mem::{align_of_logic, size_of_logic, size_of_val_logic};
3use crate::{
4 ghost::perm::{Container, Perm},
5 prelude::*,
6};
7use core::marker::PhantomData;
8#[cfg(creusot)]
9use core::ptr::Pointee;
10
11#[cfg(not(feature = "std"))]
12use alloc::boxed::Box;
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(self.addr_logic()@ + offset * size_of_logic::<T>() < usize::MAX@)]
199 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
200 fn offset_logic(self, offset: Int) -> Self;
201
202 #[logic(law)]
204 #[ensures(self.offset_logic(0) == self)]
205 fn offset_logic_zero(self);
206
207 #[logic(law)]
209 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
210 fn offset_logic_assoc(self, offset1: Int, offset2: Int);
211
212 #[logic]
216 fn sub_logic(self, rhs: Self) -> Int;
217
218 #[logic(law)]
219 #[ensures(self.sub_logic(self) == 0)]
220 fn sub_logic_refl(self);
221
222 #[logic(law)]
223 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
224 fn sub_offset_logic(self, offset: Int);
225}
226
227impl<T> SizedPointerExt<T> for *const T {
228 #[trusted]
229 #[logic(opaque)]
230 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() < usize::MAX@)]
231 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
232 fn offset_logic(self, offset: Int) -> Self {
233 dead
234 }
235
236 #[trusted]
237 #[logic(law)]
238 #[ensures(self.offset_logic(0) == self)]
239 fn offset_logic_zero(self) {}
240
241 #[trusted]
242 #[logic(law)]
243 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
244 fn offset_logic_assoc(self, offset1: Int, offset2: Int) {}
245
246 #[allow(unused)]
247 #[trusted]
248 #[logic(opaque)]
249 fn sub_logic(self, rhs: Self) -> Int {
250 dead
251 }
252
253 #[trusted]
254 #[logic(law)]
255 #[ensures(self.sub_logic(self) == 0)]
256 fn sub_logic_refl(self) {}
257
258 #[trusted]
259 #[logic(law)]
260 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
261 fn sub_offset_logic(self, offset: Int) {}
262}
263
264impl<T> SizedPointerExt<T> for *mut T {
266 #[logic(open, inline)]
267 #[requires(self.addr_logic()@ + offset * size_of_logic::<T>() < usize::MAX@)]
268 #[ensures(result.addr_logic()@ == self.addr_logic()@ + offset * size_of_logic::<T>())]
269 fn offset_logic(self, offset: Int) -> Self {
270 pearlite! { (self as *const T).offset_logic(offset) as *mut T }
271 }
272
273 #[logic(law)]
274 #[ensures(self.offset_logic(0) == self)]
275 fn offset_logic_zero(self) {}
276
277 #[logic(law)]
278 #[ensures(self.offset_logic(offset1).offset_logic(offset2) == self.offset_logic(offset1 + offset2))]
279 fn offset_logic_assoc(self, offset1: Int, offset2: Int) {}
280
281 #[logic(open, inline)]
282 fn sub_logic(self, rhs: Self) -> Int {
283 pearlite! { (self as *const T).sub_logic(rhs as *const T) }
284 }
285
286 #[logic(law)]
287 #[ensures(self.sub_logic(self) == 0)]
288 fn sub_logic_refl(self) {}
289
290 #[logic(law)]
291 #[ensures(self.offset_logic(offset).sub_logic(self) == offset)]
292 fn sub_offset_logic(self, offset: Int) {}
293}
294
295pub trait SlicePointerExt<T>: PointerExt<[T]> {
300 #[logic]
302 fn thin(self) -> *const T;
303
304 #[logic]
306 fn len_logic(self) -> usize;
307
308 #[logic(law)]
310 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
311 fn slice_ptr_ext(self, other: Self);
312}
313
314impl<T> SlicePointerExt<T> for *const [T] {
315 #[logic(open, inline)]
317 fn thin(self) -> *const T {
318 self as *const T
319 }
320
321 #[logic(open, inline)]
323 fn len_logic(self) -> usize {
324 pearlite! { metadata_logic(self) }
325 }
326
327 #[trusted]
329 #[logic(law)]
330 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
331 fn slice_ptr_ext(self, other: Self) {}
332}
333
334impl<T> SlicePointerExt<T> for *mut [T] {
335 #[logic(open, inline)]
337 fn thin(self) -> *const T {
338 self as *const T
339 }
340
341 #[logic(open, inline)]
343 fn len_logic(self) -> usize {
344 pearlite! { metadata_logic(self as *const [T]) }
345 }
346
347 #[logic(law)]
349 #[ensures(self.thin() == other.thin() && self.len_logic() == other.len_logic() ==> self == other)]
350 fn slice_ptr_ext(self, other: Self) {
351 (self as *const [T]).slice_ptr_ext(other as *const [T])
352 }
353}
354
355extern_spec! {
356 impl<T: ?Sized> *const T {
357 #[check(ghost)]
358 #[ensures(result == self.addr_logic())]
359 fn addr(self) -> usize;
360
361 #[check(ghost)]
362 #[ensures(result == self.is_null_logic())]
363 fn is_null(self) -> bool;
364
365 #[check(ghost)]
366 #[erasure]
367 #[ensures(result == self as _)]
368 fn cast<U>(self) -> *const U {
369 self as _
370 }
371
372 #[check(ghost)]
373 #[erasure]
374 #[ensures(result == self as _)]
375 const fn cast_mut(self) -> *mut T {
376 self as _
377 }
378
379 #[check(terminates)]
380 #[erasure]
381 #[ensures(result == self.is_aligned_logic())]
382 fn is_aligned(self) -> bool
383 where T: Sized,
384 {
385 self.is_aligned_to(core::mem::align_of::<T>())
386 }
387
388 #[check(ghost)]
389 #[erasure]
390 #[bitwise_proof]
391 #[requires(align != 0usize && align & (align - 1usize) == 0usize)]
392 #[ensures(result == self.is_aligned_to_logic(align))]
393 fn is_aligned_to(self, align: usize) -> bool
394 {
395 if !align.is_power_of_two() {
396 ::core::panic::panic_2021!("is_aligned_to: align is not a power-of-two");
397 }
398 self.addr() & (align - 1) == 0
399 }
400 }
401
402 impl<T: ?Sized> *mut T {
403 #[check(ghost)]
404 #[ensures(result == self.addr_logic())]
405 fn addr(self) -> usize;
406
407 #[check(ghost)]
408 #[ensures(result == self.is_null_logic())]
409 fn is_null(self) -> bool;
410
411 #[check(ghost)]
412 #[erasure]
413 #[ensures(result == self as _)]
414 fn cast<U>(self) -> *mut U {
415 self as _
416 }
417
418 #[check(ghost)]
419 #[erasure]
420 #[ensures(result == self as _)]
421 fn cast_const(self) -> *const T {
422 self as _
423 }
424
425 #[check(terminates)]
426 #[erasure]
427 #[ensures(result == self.is_aligned_logic())]
428 fn is_aligned(self) -> bool
429 where T: Sized,
430 {
431 self.is_aligned_to(core::mem::align_of::<T>())
432 }
433
434 #[check(ghost)]
435 #[erasure]
436 #[bitwise_proof]
437 #[requires(align != 0usize && align & (align - 1usize) == 0usize)]
438 #[ensures(result == self.is_aligned_to_logic(align))]
439 fn is_aligned_to(self, align: usize) -> bool
440 {
441 if !align.is_power_of_two() {
442 ::core::panic::panic_2021!("is_aligned_to: align is not a power-of-two");
443 }
444 self.addr() & (align - 1) == 0
445 }
446 }
447
448 impl<T> *const [T] {
449 #[ensures(result == metadata_logic(self))]
450 fn len(self) -> usize;
451 }
452
453 impl<T> *mut [T] {
454 #[ensures(result == metadata_logic(self))]
455 fn len(self) -> usize;
456 }
457
458 mod core {
459 mod ptr {
460 #[check(ghost)]
461 #[ensures(result.is_null_logic())]
462 fn null<T>() -> *const T
463 where
464 T: core::ptr::Thin + ?Sized;
465
466 #[check(ghost)]
467 #[ensures(result.is_null_logic())]
468 fn null_mut<T>() -> *mut T
469 where
470 T: core::ptr::Thin + ?Sized;
471
472 #[check(ghost)]
473 #[ensures(result == (p.addr_logic() == q.addr_logic()))]
474 fn addr_eq<T, U>(p: *const T, q: *const U) -> bool
475 where
476 T: ?Sized, U: ?Sized;
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> Container for *const T {
514 type Value = T;
515
516 #[logic(open, inline)]
517 fn is_disjoint(&self, self_val: &T, other: &Self, other_val: &T) -> bool {
518 pearlite! {
519 size_of_val_logic(*self_val) != 0 && size_of_val_logic(*other_val) != 0 ==>
520 self.addr_logic() != other.addr_logic()
521 }
522 }
523}
524
525impl<T: ?Sized> Invariant for Perm<*const T> {
526 #[logic(open, prophetic)]
527 fn invariant(self) -> bool {
528 pearlite! {
529 !self.ward().is_null_logic()
530 && metadata_matches(*self.val(), metadata_logic(*self.ward()))
531 && inv(self.val())
532 }
533 }
534}
535
536impl<T: ?Sized> Perm<*const T> {
537 #[check(terminates)] #[ensures(*result.1.ward() == result.0 && *result.1.val() == v)]
541 pub fn new(v: T) -> (*mut T, Ghost<Box<Perm<*const T>>>)
542 where
543 T: Sized,
544 {
545 Self::from_box(Box::new(v))
546 }
547
548 #[trusted]
550 #[check(terminates)] #[ensures(*result.1.ward() == result.0 && *result.1.val() == *val)]
552 #[erasure(Box::into_raw)]
553 pub fn from_box(val: Box<T>) -> (*mut T, Ghost<Box<Perm<*const T>>>) {
554 (Box::into_raw(val), Ghost::conjure())
555 }
556
557 #[trusted]
569 #[check(terminates)] #[ensures(*result.1.ward() == result.0)]
571 #[ensures(*result.1.val() == *r)]
572 #[intrinsic("perm_from_ref")]
573 pub fn from_ref(r: &T) -> (*const T, Ghost<&Perm<*const T>>) {
574 (r, Ghost::conjure())
575 }
576
577 #[trusted]
589 #[check(terminates)] #[ensures(*result.1.ward() == result.0)]
591 #[ensures(*result.1.val() == *r)]
592 #[ensures(*(^result.1.inner_logic()).val() == ^r)]
593 #[intrinsic("perm_from_mut")]
594 pub fn from_mut(r: &mut T) -> (*mut T, Ghost<&mut Perm<*const T>>) {
595 (r, Ghost::conjure())
596 }
597
598 #[trusted]
617 #[check(terminates)]
618 #[requires(ptr == *own.ward())]
619 #[ensures(*result == *own.val())]
620 #[allow(unused_variables)]
621 #[intrinsic("perm_as_ref")]
622 pub unsafe fn as_ref(ptr: *const T, own: Ghost<&Perm<*const T>>) -> &T {
623 unsafe { &*ptr }
624 }
625
626 #[trusted]
645 #[check(terminates)]
646 #[allow(unused_variables)]
647 #[requires(ptr as *const T == *own.ward())]
648 #[ensures(*result == *own.val())]
649 #[ensures((^own).ward() == own.ward())]
650 #[ensures(*(^own).val() == ^result)]
651 #[intrinsic("perm_as_mut")]
652 pub unsafe fn as_mut(ptr: *mut T, own: Ghost<&mut Perm<*const T>>) -> &mut T {
653 unsafe { &mut *ptr }
654 }
655
656 #[trusted]
665 #[check(terminates)]
666 #[requires(ptr as *const T == *own.ward())]
667 #[ensures(*result == *own.val())]
668 #[allow(unused_variables)]
669 #[erasure(Box::from_raw)]
670 pub unsafe fn to_box(ptr: *mut T, own: Ghost<Box<Perm<*const T>>>) -> Box<T> {
671 unsafe { Box::from_raw(ptr) }
672 }
673
674 #[check(terminates)]
683 #[requires(ptr as *const T == *own.ward())]
684 pub unsafe fn drop(ptr: *mut T, own: Ghost<Box<Perm<*const T>>>) {
685 let _ = unsafe { Self::to_box(ptr, own) };
686 }
687}
688
689impl<T> Perm<*const [T]> {
697 #[logic(open, inline)]
699 pub fn len(self) -> Int {
700 pearlite! { self.val()@.len() }
701 }
702
703 #[trusted]
705 #[check(ghost)]
706 #[requires(0 <= index && index <= self.len())]
707 #[ensures(self.ward().thin() == result.0.ward().thin())]
708 #[ensures(self.ward().thin().offset_logic(index) == result.1.ward().thin())]
709 #[ensures(self.val()@[..index] == result.0.val()@)]
710 #[ensures(self.val()@[index..] == result.1.val()@)]
711 pub fn split_at(&self, index: Int) -> (&Self, &Self) {
712 let _ = index;
713 panic!("called ghost function in normal code")
714 }
715
716 #[trusted]
718 #[check(ghost)]
719 #[requires(0 <= index && index <= self.len())]
720 #[ensures(self.ward().thin() == result.0.ward().thin())]
721 #[ensures(self.ward().thin().offset_logic(index) == result.1.ward().thin())]
722 #[ensures(self.val()@[..index] == result.0.val()@)]
723 #[ensures(self.val()@[index..] == result.1.val()@)]
724 #[ensures((^self).ward() == self.ward())]
725 #[ensures((^result.0).val()@.len() == index)]
726 #[ensures((^self).val()@ == (^result.0).val()@.concat((^result.1).val()@))]
727 pub fn split_at_mut(&mut self, index: Int) -> (&mut Perm<*const [T]>, &mut Perm<*const [T]>) {
728 let _ = index;
729 panic!("called ghost function in normal code")
730 }
731
732 #[trusted]
734 #[check(ghost)]
735 #[ensures(result.len() == self.len())]
736 #[ensures(forall<i> 0 <= i && i < self.len()
737 ==> *result[i].ward() == self.ward().thin().offset_logic(i)
738 && *result[i].val() == self.val()@[i])]
739 pub fn elements(&self) -> Seq<&Perm<*const T>> {
740 panic!("called ghost function in normal code")
741 }
742
743 #[trusted]
745 #[check(ghost)]
746 #[ensures(result.len() == self.len())]
747 #[ensures(forall<i> 0 <= i && i < self.len()
748 ==> *result[i].ward() == self.ward().thin().offset_logic(i)
749 && *result[i].val() == self.val()@[i])]
750 #[ensures((^self).ward() == self.ward())]
751 #[ensures(forall<i> 0 <= i && i < self.len() ==> *(^result[i]).val() == (^self).val()@[i])]
752 pub fn elements_mut(&mut self) -> Seq<&mut Perm<*const T>> {
753 panic!("called ghost function in normal code")
754 }
755
756 #[check(ghost)]
758 #[requires(0 <= index && index < self.len())]
759 #[ensures(*result.ward() == self.ward().thin().offset_logic(index))]
760 #[ensures(*result.val() == self.val()@[index])]
761 pub fn index(&self, index: Int) -> &Perm<*const T> {
762 let mut r = self.elements();
763 r.split_off_ghost(index).pop_front_ghost().unwrap()
764 }
765
766 #[check(ghost)]
768 #[requires(0 <= index && index < self.len())]
769 #[ensures(*result.ward() == self.ward().thin().offset_logic(index))]
770 #[ensures(*result.val() == self.val()@[index])]
771 #[ensures((^self).ward() == self.ward())]
772 #[ensures(*(^result).val() == (^self).val()@[index])]
773 #[ensures(forall<k: Int> 0 <= k && k < self.len() && k != index ==> (^self).val()@[k] == self.val()@[k])]
774 pub fn index_mut(&mut self, index: Int) -> &mut Perm<*const T> {
775 let mut r = self.elements_mut();
776 proof_assert! { forall<k> index < k && k < r.len() ==> r[k].val() == r[index..].tail()[k-index-1].val() };
777 let _r = snapshot! { r };
778 let result = r.split_off_ghost(index).pop_front_ghost().unwrap();
779 proof_assert! { forall<i> 0 <= i && i < index ==> r[i] == _r[i] }; result
781 }
782
783 #[trusted]
785 #[check(ghost)]
786 #[ensures(result.ward() == self.ward().thin())]
787 #[ensures(result.len()@ == self.len())]
788 pub fn live(&self) -> PtrLive<'_, T> {
789 panic!("called ghost function in normal code")
790 }
791
792 #[trusted]
794 #[check(ghost)]
795 #[ensures(result.ward() == self.ward().thin())]
796 #[ensures(result.len()@ == self.len())]
797 pub fn live_mut<'a, 'b>(self: &'b &'a mut Self) -> PtrLive<'a, T> {
798 panic!("called ghost function in normal code")
799 }
800}
801
802#[opaque]
810pub struct PtrLive<'a, T>(PhantomData<&'a T>);
811
812impl<T> Clone for PtrLive<'_, T> {
813 #[trusted]
814 #[check(ghost)]
815 #[ensures(result == *self)]
816 fn clone(&self) -> Self {
817 panic!("called ghost function in normal code")
818 }
819}
820
821impl<T> Copy for PtrLive<'_, T> {}
822
823impl<T> Invariant for PtrLive<'_, T> {
824 #[logic(open, prophetic)]
825 fn invariant(self) -> bool {
826 pearlite! {
827 self.len()@ * size_of_logic::<T>() <= isize::MAX@
830 && self.ward().addr_logic()@ + self.len()@ * size_of_logic::<T>() <= usize::MAX@
834 && self.ward().is_aligned_logic()
836 }
837 }
838}
839
840impl<T> PtrLive<'_, T> {
841 #[trusted]
843 #[logic(opaque)]
844 pub fn ward(self) -> *const T {
845 dead
846 }
847
848 #[trusted]
852 #[logic(opaque)]
853 pub fn len(self) -> usize {
854 dead
855 }
856
857 #[logic(open, inline)]
866 pub fn contains_range(self, ptr: *const T, len: Int) -> bool {
867 pearlite! {
868 let offset = ptr.sub_logic(self.ward());
869 ptr == self.ward().offset_logic(offset)
871 && 0 <= offset && offset <= self.len()@
872 && 0 <= offset + len && offset + len <= self.len()@
873 }
874 }
875}
876
877pub trait PtrAddExt<'a, T> {
898 #[requires(false)]
900 unsafe fn add_live(self, offset: usize, live: Ghost<PtrLive<'a, T>>) -> Self;
901
902 #[requires(false)]
904 unsafe fn offset_live(self, offset: isize, live: Ghost<PtrLive<'a, T>>) -> Self;
905}
906
907impl<'a, T> PtrAddExt<'a, T> for *const T {
908 #[trusted]
910 #[erasure(<*const T>::add)]
911 #[requires(live.contains_range(self, offset@))]
912 #[ensures(result == self.offset_logic(offset@))]
913 unsafe fn add_live(self, offset: usize, live: Ghost<PtrLive<'a, T>>) -> Self {
914 let _ = live;
915 unsafe { self.add(offset) }
916 }
917
918 #[trusted]
920 #[erasure(<*const T>::offset)]
921 #[requires(live.contains_range(self, offset@))]
922 #[ensures(result == self.offset_logic(offset@))]
923 unsafe fn offset_live(self, offset: isize, live: Ghost<PtrLive<'a, T>>) -> Self {
924 let _ = live;
925 unsafe { self.offset(offset) }
926 }
927}
928
929impl<'a, T> PtrAddExt<'a, T> for *mut T {
930 #[trusted]
932 #[erasure(<*mut T>::add)]
933 #[requires(live.contains_range(self, offset@))]
934 #[ensures(result == self.offset_logic(offset@))]
935 unsafe fn add_live(self, offset: usize, live: Ghost<PtrLive<'a, T>>) -> Self {
936 let _ = live;
937 unsafe { self.add(offset) }
938 }
939
940 #[trusted]
942 #[erasure(<*mut T>::offset)]
943 #[requires(live.contains_range(self, offset@))]
944 #[ensures(result == self.offset_logic(offset@))]
945 unsafe fn offset_live(self, offset: isize, live: Ghost<PtrLive<'a, T>>) -> Self {
946 let _ = live;
947 unsafe { self.offset(offset) }
948 }
949}