1use alloc::{boxed::Box, sync::Arc};
5use vstd::prelude::*;
6use vstd::raw_ptr::*;
7use vstd_extra::prelude::*;
8
9mod either;
10
11use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
12
13verus! {
14
15broadcast use {group_nonull_axioms, group_raw_ptr_axioms};
16
17#[verus_verify]
31pub unsafe trait NonNullPtr: Sized + 'static {
32 type Target;
35
36 type Permission: Inv;
44
45 const ALIGN_BITS: u32;
47
48 fn into_raw(self) -> ((res_ptr, perm): (NonNull<Self::Target>, Tracked<Self::Permission>))
58 ensures
59 Self::ptr_perm_match(res_ptr.view_ptr_mut(), perm@),
60 self.rel_perm(perm@),
61 perm@.inv(),
62 res_ptr.view_ptr_mut().addr() % (1usize << Self::ALIGN_BITS) == 0,
63 ;
64
65 unsafe fn from_raw(ptr: NonNull<Self::Target>, perm: Tracked<Self::Permission>) -> (ret: Self)
81 requires
82 Self::ptr_perm_match(ptr.view_ptr_mut(), perm@),
83 perm@.inv(),
84 ensures
85 ret.rel_perm(perm@),
86 ;
87
88 spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool;
100
101 spec fn rel_perm(self, perm: Self::Permission) -> bool;
103
104 proof fn lemma_align_bits_range()
106 ensures
107 Self::ALIGN_BITS < usize::BITS,
108 ;
109}
110
111pub unsafe trait NonNullPtrRef<'a>: NonNullPtr {
115 type Ref: 'a;
116
117 type RefPermission: Inv;
119
120 spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission;
122
123 spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool;
125
126 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission)
128 requires
129 perm.inv(),
130 ensures
131 Self::ref_perm_view_permission(perm).inv(),
132 ;
133
134 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
136 Self::RefPermission)
137 requires
138 perm.inv(),
139 ensures
140 ret.inv(),
141 Self::ref_perm_view_permission(ret) == Self::ref_perm_view_permission(*perm),
142 ;
143
144 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
146 Self::RefPermission)
147 requires
148 perm.inv(),
149 ensures
150 ret.inv(),
151 Self::ref_perm_view_permission(ret) == *perm,
152 ;
153
154 unsafe fn raw_as_ref(raw: NonNull<Self::Target>, perm: Tracked<Self::RefPermission>) -> (ret:
161 Self::Ref)
162 requires
163 Self::ptr_perm_match(raw.view_ptr_mut(), Self::ref_perm_view_permission(perm@)),
164 perm@.inv(),
165 ensures
166 Self::ref_rel_perm(ret, perm@),
167 ;
168
169 fn ref_as_raw(ptr_ref: Self::Ref) -> ((res_ptr, perm): (
171 NonNull<Self::Target>,
172 Tracked<Self::RefPermission>,
173 ))
174 ensures
175 Self::ref_rel_perm(ptr_ref, perm@),
176 Self::ptr_perm_match(res_ptr.view_ptr_mut(), Self::ref_perm_view_permission(perm@)),
177 perm@.inv(),
178 res_ptr.view_ptr_mut().addr() % (1usize << Self::ALIGN_BITS) == 0,
179 ;
180}
181
182} #[verus_verify]
185#[derive(Debug)]
186pub struct BoxRef<'a, T> {
187 inner: *mut T,
188 _marker: PhantomData<&'a T>,
189 tracked_perm: Tracked<BoxPointsToRef<'a, T>>,
190}
191
192verus! {
208
209#[verus_verify]
210impl<'a, T> BoxRef<'a, T> {
211 #[verus_spec(ret => ensures *ret == self.value())]
213 pub fn deref_target(&self) -> &'a T {
214 proof!{
215 use_type_invariant(self);
216 }
217 vstd::raw_ptr::ptr_ref(
225 self.inner,
226 Tracked(self.tracked_perm.borrow().tracked_borrow_points_to()),
227 )
228 }
229}
230
231unsafe impl<T: 'static> NonNullPtr for Box<T> {
232 type Target = T;
233
234 type Permission = BoxPointsTo<T>;
235
236 #[verifier::external_body]
241 const ALIGN_BITS: u32 = core::mem::align_of::<T>().trailing_zeros();
242
243 #[verus_spec]
244 fn into_raw(self) -> (NonNull<Self::Target>, Tracked<Self::Permission>) {
245 proof_decl! {
246 let tracked perm: (PointsTo<T>, Option<Dealloc>);
247 }
248
249 proof_with!(=> Tracked(perm));
251 let ptr = box_into_raw(self);
252
253 proof_decl!{
254 let tracked box_points_to = BoxPointsTo {
255 perm: PointsTowithDealloc::new(perm.0, perm.1),
256 };
257 }
258 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
259
260 (unsafe { NonNull::new_unchecked(ptr) }, Tracked(box_points_to))
262 }
263
264 #[verus_spec]
265 unsafe fn from_raw(
266 ptr: NonNull<Self::Target>,
267 Tracked(perm): Tracked<Self::Permission>,
268 ) -> Self {
269 proof_decl!{
270 let tracked perm = perm.tracked_get_points_to_with_dealloc();
271 }
272
273 let ptr = ptr.as_ptr();
274
275 unsafe {
278 proof_with!(Tracked(perm.points_to), Tracked(perm.dealloc));
279 box_from_raw(ptr)
280 }
281 }
282
283 open spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool {
284 ptr == perm.ptr()
285 }
286
287 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
288 perm.view_target() == *self
289 }
290
291 axiom fn lemma_align_bits_range();
292}
293
294unsafe impl<'a, T: 'static> NonNullPtrRef<'a> for Box<T> {
295 type Ref = BoxRef<'a, T>;
296
297 type RefPermission = BoxPointsToRef<'a, T>;
298
299 open spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission {
300 perm@
301 }
302
303 open spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool {
304 &&& r.value() == perm@.value()
305 &&& r.ptr() == perm@.ptr()
306 }
307
308 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission) {
309 }
310
311 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
312 Self::RefPermission) {
313 BoxPointsToRef(perm.0)
314 }
315
316 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
317 Self::RefPermission) {
318 BoxPointsToRef(perm)
319 }
320
321 unsafe fn raw_as_ref(
322 raw: NonNull<Self::Target>,
323 perm: Tracked<Self::RefPermission>,
324 ) -> Self::Ref {
325 BoxRef { inner: raw.as_ptr(), _marker: PhantomData, tracked_perm: perm }
326 }
327
328 fn ref_as_raw(ptr_ref: Self::Ref) -> (NonNull<Self::Target>, Tracked<Self::RefPermission>) {
329 proof!{
330 use_type_invariant(&ptr_ref);
331 assume(ptr_ref.ptr().addr() % (1usize << Self::ALIGN_BITS) == 0);
332 }
333 (unsafe { NonNull::new_unchecked(ptr_ref.inner) }, ptr_ref.tracked_perm)
335 }
336}
337
338impl<'a, T> BoxRef<'a, T> {
339 #[verifier::type_invariant]
340 spec fn type_inv(self) -> bool {
341 &&& self.inner@.addr != 0
342 &&& self.inner@.addr as int % vstd::layout::align_of::<T>() as int == 0
343 &&& self.tracked_perm@@.ptr() == self.inner
344 &&& self.tracked_perm@.inv()
345 }
346
347 pub closed spec fn ptr(self) -> *mut T {
348 self.inner
349 }
350
351 pub closed spec fn value(self) -> T {
352 self.tracked_perm@@.value()
353 }
354}
355
356} #[verus_verify]
361#[derive(Debug)]
362pub struct ArcRef<'a, T: 'static> {
363 inner: ManuallyDrop<Arc<T>>,
364 _marker: PhantomData<&'a Arc<T>>,
365}
366
367#[verus_verify]
368impl<T> Deref for ArcRef<'_, T> {
369 type Target = Arc<T>;
370
371 #[verus_spec(ret =>
372 ensures *ret == self@
373 )]
374 fn deref(&self) -> &Self::Target {
375 &self.inner
376 }
377}
378
379#[verus_verify]
380impl<'a, T> ArcRef<'a, T> {
381 #[verus_verify(external_body)]
385 #[verus_spec(ret => ensures *ret == *self@)]
386 pub fn deref_target(&self) -> &'a T {
387 unsafe { &*(self.deref().deref() as *const T) }
391 }
392}
393
394verus! {
395
396unsafe impl<T: 'static> NonNullPtr for Arc<T> {
397 type Target = T;
398
399 type Permission = ArcPointsTo<T>;
400
401 #[verifier::external_body]
407 const ALIGN_BITS: u32 = core::mem::align_of::<T>().trailing_zeros();
408
409 #[verus_spec]
410 fn into_raw(self) -> (NonNull<Self::Target>, Tracked<Self::Permission>) {
411 proof_decl!{
412 let tracked perm: ArcPointsTo<T>;
413 }
414 let ptr = (#[verus_spec(with => Tracked(perm))]
416 arc_into_raw(self)).cast_mut();
417 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
418
419 (unsafe { NonNull::new_unchecked(ptr) }, Tracked(perm))
421 }
422
423 unsafe fn from_raw(
424 ptr: NonNull<Self::Target>,
425 Tracked(perm): Tracked<Self::Permission>,
426 ) -> Self {
427 let ptr = ptr.as_ptr().cast_const();
428
429 unsafe {
432 #[verus_spec(with Tracked(perm))]
433 arc_from_raw(ptr)
434 }
435 }
436
437 open spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool {
438 ptr == perm.ptr()
439 }
440
441 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
442 perm.view_target() == *self
443 }
444
445 axiom fn lemma_align_bits_range();
446}
447
448unsafe impl<'a, T: 'static> NonNullPtrRef<'a> for Arc<T> {
449 type Ref = ArcRef<'a, T>;
450
451 type RefPermission = ArcPointsTo<T>;
452
453 open spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission {
454 perm
455 }
456
457 open spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool {
458 perm.view_target() == *r@
459 }
460
461 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission) {
462 }
463
464 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
465 Self::RefPermission) {
466 ArcPointsTo { perm: perm.perm }
467 }
468
469 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
470 Self::RefPermission) {
471 ArcPointsTo { perm: perm.perm }
472 }
473
474 unsafe fn raw_as_ref(
475 raw: NonNull<Self::Target>,
476 perm: Tracked<Self::RefPermission>,
477 ) -> Self::Ref {
478 unsafe {
479 ArcRef {
480 inner: ManuallyDrop::new(
481 #[verus_spec(with perm)]
482 arc_from_raw(raw.as_ptr()),
483 ),
484 _marker: PhantomData,
485 }
486 }
487 }
488
489 fn ref_as_raw(ptr_ref: Self::Ref) -> (NonNull<Self::Target>, Tracked<Self::RefPermission>) {
490 NonNullPtr::into_raw(ManuallyDrop::into_inner(ptr_ref.inner))
491 }
492}
493
494impl<T> View for ArcRef<'_, T> {
495 type V = Arc<T>;
496
497 closed spec fn view(&self) -> Arc<T> {
498 self.inner@
499 }
500}
501
502}