1use alloc::{boxed::Box, sync::Arc};
5use vstd::prelude::*;
6use vstd::raw_ptr::*;
7#[cfg(feature = "irc11")]
8use vstd::thread_view::Objective;
9use vstd_extra::prelude::*;
10
11mod either;
12
13use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
14
15verus! {
16
17broadcast use {group_nonull_axioms, group_raw_ptr_axioms};
18#[verus_verify]
34pub unsafe trait NonNullPtr: Sized + 'static {
35 type Target;
38
39 #[cfg(not(feature = "irc11"))]
47 type Permission: Inv;
48
49 #[cfg(feature = "irc11")]
50 type Permission: Inv + Objective;
51
52 const ALIGN_BITS: u32;
54
55 fn into_raw(self) -> ((res_ptr, perm): (NonNull<Self::Target>, Tracked<Self::Permission>))
65 ensures
66 Self::ptr_perm_match(res_ptr.view_ptr_mut(), perm@),
67 self.rel_perm(perm@),
68 perm@.inv(),
69 res_ptr.view_ptr_mut().addr() % (1usize << Self::ALIGN_BITS) == 0,
70 ;
71
72 unsafe fn from_raw(ptr: NonNull<Self::Target>, perm: Tracked<Self::Permission>) -> (ret: Self)
88 requires
89 Self::ptr_perm_match(ptr.view_ptr_mut(), perm@),
90 perm@.inv(),
91 ensures
92 ret.rel_perm(perm@),
93 ;
94
95 spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool;
107
108 spec fn rel_perm(self, perm: Self::Permission) -> bool;
110
111 proof fn lemma_align_bits_range()
113 ensures
114 Self::ALIGN_BITS < usize::BITS,
115 ;
116}
117
118pub unsafe trait NonNullPtrRef<'a>: NonNullPtr {
122 type Ref: 'a;
123
124 type RefPermission: Inv;
126
127 spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission;
129
130 spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool;
132
133 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission)
135 requires
136 perm.inv(),
137 ensures
138 Self::ref_perm_view_permission(perm).inv(),
139 ;
140
141 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
143 Self::RefPermission)
144 requires
145 perm.inv(),
146 ensures
147 ret.inv(),
148 Self::ref_perm_view_permission(ret) == Self::ref_perm_view_permission(*perm),
149 ;
150
151 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
153 Self::RefPermission)
154 requires
155 perm.inv(),
156 ensures
157 ret.inv(),
158 Self::ref_perm_view_permission(ret) == *perm,
159 ;
160
161 unsafe fn raw_as_ref(raw: NonNull<Self::Target>, perm: Tracked<Self::RefPermission>) -> (ret:
168 Self::Ref)
169 requires
170 Self::ptr_perm_match(raw.view_ptr_mut(), Self::ref_perm_view_permission(perm@)),
171 perm@.inv(),
172 ensures
173 Self::ref_rel_perm(ret, perm@),
174 ;
175
176 fn ref_as_raw(ptr_ref: Self::Ref) -> ((res_ptr, perm): (
178 NonNull<Self::Target>,
179 Tracked<Self::RefPermission>,
180 ))
181 ensures
182 Self::ref_rel_perm(ptr_ref, perm@),
183 Self::ptr_perm_match(res_ptr.view_ptr_mut(), Self::ref_perm_view_permission(perm@)),
184 perm@.inv(),
185 res_ptr.view_ptr_mut().addr() % (1usize << Self::ALIGN_BITS) == 0,
186 ;
187}
188
189} #[verus_verify]
192#[derive(Debug)]
193pub struct BoxRef<'a, T> {
194 inner: *mut T,
195 _marker: PhantomData<&'a T>,
196 tracked_perm: Tracked<BoxPointsToRef<'a, T>>,
197}
198
199verus! {
215
216#[verus_verify]
217impl<'a, T> BoxRef<'a, T> {
218 #[verus_spec(ret => ensures *ret == self.value())]
220 pub fn deref_target(&self) -> &'a T {
221 proof!{
222 use_type_invariant(self);
223 }
224 vstd::raw_ptr::ptr_ref(
232 self.inner,
233 Tracked(self.tracked_perm.borrow().tracked_borrow_points_to()),
234 )
235 }
236}
237
238unsafe impl<T: 'static> NonNullPtr for Box<T> {
239 type Target = T;
240
241 type Permission = BoxPointsTo<T>;
242
243 #[verifier::external_body]
248 const ALIGN_BITS: u32 = core::mem::align_of::<T>().trailing_zeros();
249
250 #[verus_spec]
251 fn into_raw(self) -> (NonNull<Self::Target>, Tracked<Self::Permission>) {
252 proof_decl! {
253 let tracked perm: (PointsTo<T>, Option<Dealloc>);
254 }
255
256 proof_with!(=> Tracked(perm));
258 let ptr = box_into_raw(self);
259
260 proof_decl!{
261 let tracked box_points_to = BoxPointsTo {
262 perm: PointsTowithDealloc::new(perm.0, perm.1),
263 };
264 }
265 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
266
267 (unsafe { NonNull::new_unchecked(ptr) }, Tracked(box_points_to))
269 }
270
271 #[verus_spec]
272 unsafe fn from_raw(
273 ptr: NonNull<Self::Target>,
274 Tracked(perm): Tracked<Self::Permission>,
275 ) -> Self {
276 proof_decl!{
277 let tracked perm = perm.tracked_get_points_to_with_dealloc();
278 }
279
280 let ptr = ptr.as_ptr();
281
282 unsafe {
285 proof_with!(Tracked(perm.points_to), Tracked(perm.dealloc));
286 box_from_raw(ptr)
287 }
288 }
289
290 open spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool {
291 ptr == perm.ptr()
292 }
293
294 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
295 perm.view_target() == *self
296 }
297
298 axiom fn lemma_align_bits_range();
299}
300
301unsafe impl<'a, T: 'static> NonNullPtrRef<'a> for Box<T> {
302 type Ref = BoxRef<'a, T>;
303
304 type RefPermission = BoxPointsToRef<'a, T>;
305
306 open spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission {
307 perm@
308 }
309
310 open spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool {
311 &&& r.value() == perm@.value()
312 &&& r.ptr() == perm@.ptr()
313 }
314
315 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission) {
316 }
317
318 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
319 Self::RefPermission) {
320 BoxPointsToRef(perm.0)
321 }
322
323 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
324 Self::RefPermission) {
325 BoxPointsToRef(perm)
326 }
327
328 unsafe fn raw_as_ref(
329 raw: NonNull<Self::Target>,
330 perm: Tracked<Self::RefPermission>,
331 ) -> Self::Ref {
332 BoxRef { inner: raw.as_ptr(), _marker: PhantomData, tracked_perm: perm }
333 }
334
335 fn ref_as_raw(ptr_ref: Self::Ref) -> (NonNull<Self::Target>, Tracked<Self::RefPermission>) {
336 proof!{
337 use_type_invariant(&ptr_ref);
338 assume(ptr_ref.ptr().addr() % (1usize << Self::ALIGN_BITS) == 0);
339 }
340 (unsafe { NonNull::new_unchecked(ptr_ref.inner) }, ptr_ref.tracked_perm)
342 }
343}
344
345impl<'a, T> BoxRef<'a, T> {
346 #[verifier::type_invariant]
347 spec fn type_inv(self) -> bool {
348 &&& self.inner@.addr != 0
349 &&& self.inner@.addr as int % vstd::layout::align_of::<T>() as int == 0
350 &&& self.tracked_perm@@.ptr() == self.inner
351 &&& self.tracked_perm@.inv()
352 }
353
354 pub closed spec fn ptr(self) -> *mut T {
355 self.inner
356 }
357
358 pub closed spec fn value(self) -> T {
359 self.tracked_perm@@.value()
360 }
361}
362
363} #[verus_verify]
368#[derive(Debug)]
369pub struct ArcRef<'a, T: 'static> {
370 inner: ManuallyDrop<Arc<T>>,
371 _marker: PhantomData<&'a Arc<T>>,
372}
373
374#[verus_verify]
375impl<T> Deref for ArcRef<'_, T> {
376 type Target = Arc<T>;
377
378 #[verus_spec(ret =>
379 ensures *ret == self@
380 )]
381 fn deref(&self) -> &Self::Target {
382 &self.inner
383 }
384}
385
386#[verus_verify]
387impl<'a, T> ArcRef<'a, T> {
388 #[verus_verify(external_body)]
392 #[verus_spec(ret => ensures *ret == *self@)]
393 pub fn deref_target(&self) -> &'a T {
394 unsafe { &*(self.deref().deref() as *const T) }
398 }
399}
400
401verus! {
402
403unsafe impl<T: 'static> NonNullPtr for Arc<T> {
404 type Target = T;
405
406 type Permission = ArcPointsTo<T>;
407
408 #[verifier::external_body]
414 const ALIGN_BITS: u32 = core::mem::align_of::<T>().trailing_zeros();
415
416 #[verus_spec]
417 fn into_raw(self) -> (NonNull<Self::Target>, Tracked<Self::Permission>) {
418 proof_decl!{
419 let tracked perm: ArcPointsTo<T>;
420 }
421 let ptr = (#[verus_spec(with => Tracked(perm))]
423 arc_into_raw(self)).cast_mut();
424 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
425
426 (unsafe { NonNull::new_unchecked(ptr) }, Tracked(perm))
428 }
429
430 unsafe fn from_raw(
431 ptr: NonNull<Self::Target>,
432 Tracked(perm): Tracked<Self::Permission>,
433 ) -> Self {
434 let ptr = ptr.as_ptr().cast_const();
435
436 unsafe {
439 #[verus_spec(with Tracked(perm))]
440 arc_from_raw(ptr)
441 }
442 }
443
444 open spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool {
445 ptr == perm.ptr()
446 }
447
448 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
449 perm.view_target() == *self
450 }
451
452 axiom fn lemma_align_bits_range();
453}
454
455unsafe impl<'a, T: 'static> NonNullPtrRef<'a> for Arc<T> {
456 type Ref = ArcRef<'a, T>;
457
458 type RefPermission = ArcPointsTo<T>;
459
460 open spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission {
461 perm
462 }
463
464 open spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool {
465 perm.view_target() == *r@
466 }
467
468 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission) {
469 }
470
471 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
472 Self::RefPermission) {
473 ArcPointsTo { perm: perm.perm }
474 }
475
476 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
477 Self::RefPermission) {
478 ArcPointsTo { perm: perm.perm }
479 }
480
481 unsafe fn raw_as_ref(
482 raw: NonNull<Self::Target>,
483 perm: Tracked<Self::RefPermission>,
484 ) -> Self::Ref {
485 unsafe {
486 ArcRef {
487 inner: ManuallyDrop::new(
488 #[verus_spec(with perm)]
489 arc_from_raw(raw.as_ptr()),
490 ),
491 _marker: PhantomData,
492 }
493 }
494 }
495
496 fn ref_as_raw(ptr_ref: Self::Ref) -> (NonNull<Self::Target>, Tracked<Self::RefPermission>) {
497 NonNullPtr::into_raw(ManuallyDrop::into_inner(ptr_ref.inner))
498 }
499}
500
501impl<T> View for ArcRef<'_, T> {
502 type V = Arc<T>;
503
504 closed spec fn view(&self) -> Arc<T> {
505 self.inner@
506 }
507}
508
509}