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
13use crate::prelude::*;
14
15verus! {
16
17broadcast use {group_nonull_axioms, group_raw_ptr_axioms};
18
19#[verus_verify]
33pub unsafe trait NonNullPtr: Sized + 'static {
34 type Target;
37
38 type Permission: Inv;
46
47 const ALIGN_BITS: u32;
49
50 fn into_raw(self) -> ((res_ptr, perm): (NonNull<Self::Target>, Tracked<Self::Permission>))
60 ensures
61 Self::ptr_perm_match(res_ptr.view_ptr_mut(), perm@),
62 self.rel_perm(perm@),
63 perm@.inv(),
64 res_ptr.view_ptr_mut().addr() % (1usize << Self::ALIGN_BITS) == 0,
65 ;
66
67 unsafe fn from_raw(ptr: NonNull<Self::Target>, perm: Tracked<Self::Permission>) -> (ret: Self)
83 requires
84 Self::ptr_perm_match(ptr.view_ptr_mut(), perm@),
85 perm@.inv(),
86 ensures
87 ret.rel_perm(perm@),
88 ;
89
90 spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool;
102
103 spec fn rel_perm(self, perm: Self::Permission) -> bool;
105
106 proof fn lemma_align_bits_range()
108 ensures
109 Self::ALIGN_BITS < usize::BITS,
110 ;
111}
112
113pub unsafe trait NonNullPtrRef<'a>: NonNullPtr {
117 type Ref: 'a;
118
119 type RefPermission: Inv;
121
122 spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission;
124
125 spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool;
127
128 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission)
130 requires
131 perm.inv(),
132 ensures
133 Self::ref_perm_view_permission(perm).inv(),
134 ;
135
136 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
138 Self::RefPermission)
139 requires
140 perm.inv(),
141 ensures
142 ret.inv(),
143 Self::ref_perm_view_permission(ret) == Self::ref_perm_view_permission(*perm),
144 ;
145
146 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
148 Self::RefPermission)
149 requires
150 perm.inv(),
151 ensures
152 ret.inv(),
153 Self::ref_perm_view_permission(ret) == *perm,
154 ;
155
156 unsafe fn raw_as_ref(raw: NonNull<Self::Target>, perm: Tracked<Self::RefPermission>) -> (ret:
163 Self::Ref)
164 requires
165 Self::ptr_perm_match(raw.view_ptr_mut(), Self::ref_perm_view_permission(perm@)),
166 perm@.inv(),
167 ensures
168 Self::ref_rel_perm(ret, perm@),
169 ;
170
171 fn ref_as_raw(ptr_ref: Self::Ref) -> ((res_ptr, perm): (
173 NonNull<Self::Target>,
174 Tracked<Self::RefPermission>,
175 ))
176 ensures
177 Self::ref_rel_perm(ptr_ref, perm@),
178 Self::ptr_perm_match(res_ptr.view_ptr_mut(), Self::ref_perm_view_permission(perm@)),
179 perm@.inv(),
180 res_ptr.view_ptr_mut().addr() % (1usize << Self::ALIGN_BITS) == 0,
181 ;
182}
183
184#[verus_verify]
186#[derive(Debug)]
187pub struct BoxRef<'a, T> {
188 inner: *mut T,
189 _marker: PhantomData<&'a T>,
190 tracked_perm: Tracked<BoxPointsToRef<'a, T>>,
191}
192
193impl<'a, T> BoxRef<'a, T> {
194 #[verifier::type_invariant]
195 spec fn type_inv(self) -> bool {
196 &&& self.inner@.addr != 0
197 &&& self.inner@.addr as int % vstd::layout::align_of::<T>() as int == 0
198 &&& self.tracked_perm@@.ptr() == self.inner
199 &&& self.tracked_perm@.inv()
200 }
201
202 pub closed spec fn ptr(self) -> *mut T {
203 self.inner
204 }
205
206 pub closed spec fn value(self) -> T {
207 self.tracked_perm@@.value()
208 }
209}
210
211#[verus_verify]
227impl<'a, T> BoxRef<'a, T> {
228 #[verus_spec(ret => ensures *ret == self.value())]
230 pub fn deref_target(&self) -> &'a T {
231 proof!{
232 use_type_invariant(self);
233 }
234 vstd::raw_ptr::ptr_ref(
241 self.inner,
242 Tracked(self.tracked_perm.borrow().tracked_borrow_points_to()),
243 )
244 }
245}
246
247unsafe impl<T: 'static> NonNullPtr for Box<T> {
248 type Target = T;
249
250 type Permission = BoxPointsTo<T>;
251
252 #[verifier::external_body]
257 const ALIGN_BITS: u32 = core::mem::align_of::<T>().trailing_zeros();
258
259 #[verus_spec]
260 fn into_raw(self) -> (NonNull<Self::Target>, Tracked<Self::Permission>) {
261 proof_decl! {
262 let tracked perm: (PointsTo<T>, Option<Dealloc>);
263 }
264
265 proof_with!(=> Tracked(perm));
267 let ptr = box_into_raw(self);
268
269 proof_decl!{
270 let tracked box_points_to = BoxPointsTo {
271 perm: PointsTowithDealloc::new(perm.0, perm.1),
272 };
273 }
274 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
275
276 (unsafe { NonNull::new_unchecked(ptr) }, Tracked(box_points_to))
278 }
279
280 #[verus_spec]
281 unsafe fn from_raw(
282 ptr: NonNull<Self::Target>,
283 Tracked(perm): Tracked<Self::Permission>,
284 ) -> Self {
285 proof_decl!{
286 let tracked perm = perm.tracked_get_points_to_with_dealloc();
287 }
288
289 let ptr = ptr.as_ptr();
290
291 unsafe {
294 proof_with!(Tracked(perm.points_to), Tracked(perm.dealloc));
295 box_from_raw(ptr)
296 }
297 }
298
299 open spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool {
300 ptr == perm.ptr()
301 }
302
303 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
304 perm.view_target() == *self
305 }
306
307 axiom fn lemma_align_bits_range();
308}
309
310unsafe impl<'a, T: 'static> NonNullPtrRef<'a> for Box<T> {
311 type Ref = BoxRef<'a, T>;
312
313 type RefPermission = BoxPointsToRef<'a, T>;
314
315 open spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission {
316 perm@
317 }
318
319 open spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool {
320 &&& r.value() == perm@.value()
321 &&& r.ptr() == perm@.ptr()
322 }
323
324 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission) {
325 }
326
327 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
328 Self::RefPermission) {
329 BoxPointsToRef(perm.0)
330 }
331
332 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
333 Self::RefPermission) {
334 BoxPointsToRef(perm)
335 }
336
337 unsafe fn raw_as_ref(
338 raw: NonNull<Self::Target>,
339 perm: Tracked<Self::RefPermission>,
340 ) -> Self::Ref {
341 BoxRef { inner: raw.as_ptr(), _marker: PhantomData, tracked_perm: perm }
342 }
343
344 fn ref_as_raw(ptr_ref: Self::Ref) -> (NonNull<Self::Target>, Tracked<Self::RefPermission>) {
345 proof!{
346 use_type_invariant(&ptr_ref);
347 assume(ptr_ref.ptr().addr() % (1usize << Self::ALIGN_BITS) == 0);
348 }
349 (unsafe { NonNull::new_unchecked(ptr_ref.inner) }, ptr_ref.tracked_perm)
351 }
352}
353
354#[verus_verify]
358#[derive(Debug)]
359pub struct ArcRef<'a, T: 'static> {
360 inner: ManuallyDrop<Arc<T>>,
361 _marker: PhantomData<&'a Arc<T>>,
362}
363
364impl<T> View for ArcRef<'_, T> {
365 type V = Arc<T>;
366
367 closed spec fn view(&self) -> Arc<T> {
368 self.inner@
369 }
370}
371
372#[verus_verify]
373impl<T> Deref for ArcRef<'_, T> {
374 type Target = Arc<T>;
375
376 #[verus_spec(ret =>
377 ensures *ret == self@
378 )]
379 fn deref(&self) -> &Self::Target {
380 &self.inner
381 }
382}
383
384#[verus_verify]
385impl<'a, T> ArcRef<'a, T> {
386 #[verus_verify(external_body)]
390 #[verus_spec(ret => ensures *ret == *self@)]
391 pub fn deref_target(&self) -> &'a T {
392 unsafe { &*(self.deref().deref() as *const T) }
396 }
397}
398
399unsafe impl<T: 'static> NonNullPtr for Arc<T> {
400 type Target = T;
401
402 type Permission = ArcPointsTo<T>;
403
404 #[verifier::external_body]
410 const ALIGN_BITS: u32 = core::mem::align_of::<T>().trailing_zeros();
411
412 #[verus_spec]
413 fn into_raw(self) -> (NonNull<Self::Target>, Tracked<Self::Permission>) {
414 proof_decl!{
415 let tracked perm: ArcPointsTo<T>;
416 }
417 let ptr = (#[verus_spec(with => Tracked(perm))]
419 arc_into_raw(self)).cast_mut();
420 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
421
422 (unsafe { NonNull::new_unchecked(ptr) }, Tracked(perm))
424 }
425
426 unsafe fn from_raw(
427 ptr: NonNull<Self::Target>,
428 Tracked(perm): Tracked<Self::Permission>,
429 ) -> Self {
430 let ptr = ptr.as_ptr().cast_const();
431
432 unsafe {
435 #[verus_spec(with Tracked(perm))]
436 arc_from_raw(ptr)
437 }
438 }
439
440 open spec fn ptr_perm_match(ptr: *mut Self::Target, perm: Self::Permission) -> bool {
441 ptr == perm.ptr()
442 }
443
444 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
445 perm.view_target() == *self
446 }
447
448 axiom fn lemma_align_bits_range();
449}
450
451unsafe impl<'a, T: 'static> NonNullPtrRef<'a> for Arc<T> {
452 type Ref = ArcRef<'a, T>;
453
454 type RefPermission = ArcPointsTo<T>;
455
456 open spec fn ref_perm_view_permission(perm: Self::RefPermission) -> Self::Permission {
457 perm
458 }
459
460 open spec fn ref_rel_perm(r: Self::Ref, perm: Self::RefPermission) -> bool {
461 perm.view_target() == *r@
462 }
463
464 proof fn lemma_ref_perm_inv_impl_perm_inv(perm: Self::RefPermission) {
465 }
466
467 proof fn borrow_ref_perm(tracked perm: &Self::RefPermission) -> (tracked ret:
468 Self::RefPermission) {
469 ArcPointsTo { perm: perm.perm }
470 }
471
472 proof fn borrow_perm_as_ref_perm(tracked perm: &'a Self::Permission) -> (tracked ret:
473 Self::RefPermission) {
474 ArcPointsTo { perm: perm.perm }
475 }
476
477 unsafe fn raw_as_ref(
478 raw: NonNull<Self::Target>,
479 perm: Tracked<Self::RefPermission>,
480 ) -> Self::Ref {
481 unsafe {
482 ArcRef {
483 inner: ManuallyDrop::new(
484 #[verus_spec(with perm)]
485 arc_from_raw(raw.as_ptr()),
486 ),
487 _marker: PhantomData,
488 }
489 }
490 }
491
492 fn ref_as_raw(ptr_ref: Self::Ref) -> (NonNull<Self::Target>, Tracked<Self::RefPermission>) {
493 NonNullPtr::into_raw(ManuallyDrop::into_inner(ptr_ref.inner))
494 }
495}
496
497}