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