1use vstd::prelude::*;
2
3use vstd::layout;
4use vstd::raw_ptr;
5use vstd::set;
6use vstd::set_lib;
7
8use core::marker::PhantomData;
9
10verus! {
11
12pub struct ArrayPtr<V, const N: usize> {
15 pub addr: usize,
16 pub index: usize,
17 pub _type: PhantomData<[V; N]>,
18}
19
20#[verifier::external_body]
21#[verifier::accept_recursive_types(V)]
22pub tracked struct PointsToArray<V, const N: usize> {
23 phantom: core::marker::PhantomData<[V; N]>,
24 no_copy: NoCopy,
25}
26
27pub ghost struct PointsToArrayData<V, const N: usize> {
28 pub ptr: *mut [V; N],
29 pub value: [raw_ptr::MemContents<V>; N],
30}
31
32#[verifier::inline]
33pub open spec fn is_mem_contents_all_init<V, const N: usize>(
34 arr: [raw_ptr::MemContents<V>; N],
35) -> bool {
36 forall|index: int| 0 <= index < N ==> #[trigger] arr[index].is_init()
37}
38
39#[verifier::inline]
40pub open spec fn is_mem_contents_all_uninit<V, const N: usize>(
41 arr: [raw_ptr::MemContents<V>; N],
42) -> bool {
43 forall|index: int| 0 <= index < N ==> #[trigger] arr[index].is_uninit()
44}
45
46pub uninterp spec fn mem_contents_unwrap<V, const N: usize>(
47 arr: [raw_ptr::MemContents<V>; N],
48) -> (res: raw_ptr::MemContents<[V; N]>)
49 recommends
50 is_mem_contents_all_init(arr) || is_mem_contents_all_uninit(arr),
51;
52
53pub uninterp spec fn mem_contents_wrap<V, const N: usize>(
54 data: raw_ptr::MemContents<[V; N]>,
55) -> (res: [raw_ptr::MemContents<V>; N]);
56
57pub axiom fn axiom_mem_contents_unwrap_init_correctness<V, const N: usize>(
58 arr: [raw_ptr::MemContents<V>; N],
59 res: raw_ptr::MemContents<[V; N]>,
60)
61 requires
62 res == mem_contents_unwrap(arr),
63 is_mem_contents_all_init(arr),
64 ensures
65 res.is_init(),
66 forall|index: int| 0 <= index < N ==> #[trigger] res.value()[index] == arr[index].value(),
67;
68
69pub axiom fn axiom_mem_contents_unwrap_uninit_correctness<V, const N: usize>(
70 arr: [raw_ptr::MemContents<V>; N],
71 res: raw_ptr::MemContents<[V; N]>,
72)
73 requires
74 res == mem_contents_unwrap(arr),
75 is_mem_contents_all_uninit(arr),
76 ensures
77 res.is_uninit(),
78;
79
80pub axiom fn axiom_mem_contents_wrap_correctness<V, const N: usize>(
81 data: raw_ptr::MemContents<[V; N]>,
82 res: [raw_ptr::MemContents<V>; N],
83)
84 requires
85 res == mem_contents_wrap(data),
86 ensures
87 data.is_uninit() ==> is_mem_contents_all_uninit(res),
88 data.is_init() ==> is_mem_contents_all_init(res) && forall|index: int|
89 0 <= index < N ==> #[trigger] res[index].value() == data.value()[index],
90;
91
92impl<V, const N: usize> PointsToArrayData<V, N> {
93 #[verifier::external_body]
94 pub proof fn into_ptr(tracked self) -> (tracked data: raw_ptr::PointsToData<[V; N]>)
95 ensures
96 data.ptr == self.ptr,
97 data.opt_value == mem_contents_unwrap(self.value),
98 {
99 unimplemented!();
100 }
101
102 #[verifier::external_body]
103 pub proof fn into_array(tracked data: raw_ptr::PointsToData<[V; N]>) -> (tracked res:
104 PointsToArrayData<V, N>)
105 ensures
106 res.ptr == data.ptr,
107 res.value == mem_contents_wrap(data.opt_value),
108 {
109 unimplemented!();
110 }
111}
112
113impl<T, const N: usize> View for PointsToArray<T, N> {
114 type V = PointsToArrayData<T, N>;
115
116 uninterp spec fn view(&self) -> Self::V;
117}
118
119impl<V, const N: usize> PointsToArray<V, N> {
120 #[verifier::inline]
121 pub open spec fn ptr(self) -> *mut [V; N] {
122 self@.ptr
123 }
124
125 #[verifier::inline]
126 pub open spec fn opt_value(self) -> [raw_ptr::MemContents<V>; N] {
127 self@.value
128 }
129
130 #[verifier::inline]
131 pub open spec fn is_init(self, index: int) -> bool {
132 0 <= index < N && self.opt_value()[index].is_init()
133 }
134
135 #[verifier::inline]
136 pub open spec fn is_uninit(self, index: int) -> bool {
137 0 <= index < N && self.opt_value()[index].is_uninit()
138 }
139
140 #[verifier::inline]
141 pub open spec fn is_init_all(self) -> bool {
142 is_mem_contents_all_init(self.opt_value())
143 }
144
145 #[verifier::inline]
146 pub open spec fn is_uninit_all(self) -> bool {
147 is_mem_contents_all_uninit(self.opt_value())
148 }
149
150 #[verifier::inline]
151 pub open spec fn value(self) -> Seq<V>
152 recommends
153 self.is_init_all(),
154 {
155 let opt_value = self.opt_value();
156 Seq::new(N as nat, |i: int| opt_value[i].value())
157 }
158
159 #[verifier::external_body]
160 pub proof fn leak_contents(tracked &mut self, index: int)
161 ensures
162 self.ptr() == old(self).ptr(),
163 self.is_uninit(index),
164 forall|i: int|
165 0 <= i < N && i != index ==> self.opt_value()[i] == old(self).opt_value()[i],
166 {
167 unimplemented!();
168 }
169
170 #[verifier::external_body]
171 pub proof fn is_disjoint<S, const M: usize>(&self, other: &PointsToArray<S, M>)
172 ensures
173 self.ptr() as int + layout::size_of::<[V; N]>() <= other.ptr() as int
174 || other.ptr() as int + layout::size_of::<[S; M]>() <= self.ptr() as int,
175 {
176 unimplemented!();
177 }
178
179 #[verifier::external_body]
180 pub proof fn is_disjoint_ptr<S>(&self, other: &raw_ptr::PointsTo<S>)
181 ensures
182 self.ptr() as int + layout::size_of::<[V; N]>() <= other.ptr() as int
183 || other.ptr() as int + layout::size_of::<S>() <= self.ptr() as int,
184 {
185 unimplemented!();
186 }
187
188 #[verifier::external_body]
189 pub proof fn is_nonnull(tracked &self)
190 requires
191 layout::size_of::<[V; N]>() > 0,
192 ensures
193 self@.ptr@.addr != 0,
194 {
195 unimplemented!();
196 }
197}
198
199#[inline(always)]
201#[verifier::external_body]
202pub exec fn ptr_mut_fill<V, const N: usize>(
203 ptr: *mut [V; N],
204 Tracked(perm): Tracked<&mut PointsToArray<V, N>>,
205 value: V,
206) where V: Copy
207 requires
208 old(perm).ptr() == ptr,
209 old(perm).is_uninit_all(),
210 ensures
211 perm.ptr() == ptr,
212 perm.is_init_all(),
213 forall|i: int| 0 <= i < N ==> perm.opt_value()[i] == raw_ptr::MemContents::Init(value),
214 opens_invariants none
215 no_unwind
216{
217 for i in 0..N {
218 unsafe {
219 core::ptr::write((ptr as *mut V).add(i), value);
220 }
221 }
222}
223
224#[inline(always)]
225#[verifier::external_body]
226pub exec fn ptr_mut_write_at<V, const N: usize>(
227 ptr: *mut [V; N],
228 Tracked(perm): Tracked<&mut PointsToArray<V, N>>,
229 index: usize,
230 value: V,
231)
232 requires
233 old(perm).ptr() == ptr,
234 old(perm).is_uninit(index as int),
235 index < N,
236 ensures
237 perm.ptr() == ptr,
238 perm.is_init(index as int),
239 forall|i: int| 0 <= i < N && i != index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
240 perm.opt_value()[index as int] == raw_ptr::MemContents::Init(value),
241 opens_invariants none
242 no_unwind
243{
244 unsafe {
245 core::ptr::write((ptr as *mut V).add(index), value);
246 }
247}
248
249#[inline(always)]
251#[verifier::external_body]
252pub exec fn ptr_mut_read_at<V, const N: usize>(
253 ptr: *mut [V; N],
254 Tracked(perm): Tracked<&mut PointsToArray<V, N>>,
255 index: usize,
256) -> (res: V) where V: Copy
257 requires
258 old(perm).ptr() == ptr,
259 old(perm).is_init(index as int),
260 index < N,
261 ensures
262 perm.ptr() == ptr,
263 perm.is_uninit(index as int),
264 forall|i: int| 0 <= i < N && i != index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
265 res == old(perm).opt_value()[index as int].value(),
266 opens_invariants none
267 no_unwind
268{
269 unsafe { core::ptr::read((ptr as *const V).add(index)) }
270}
271
272#[inline(always)]
273#[verifier::external_body]
274pub exec fn ptr_mut_read_all<V, const N: usize>(
275 ptr: *mut [V; N],
276 Tracked(perm): Tracked<&mut PointsToArray<V, N>>,
277) -> (res: [V; N])
278 requires
279 old(perm).ptr() == ptr,
280 old(perm).is_init_all(),
281 ensures
282 perm.ptr() == ptr,
283 perm.is_uninit_all(),
284 res@ == old(perm).value(),
285 opens_invariants none
286 no_unwind
287{
288 unsafe { core::ptr::read(ptr) }
289}
290
291#[inline(always)]
293#[verifier::external_body]
294pub exec fn ptr_ref_at<V, const N: usize>(
295 ptr: *mut [V; N],
296 Tracked(perm): Tracked<&PointsToArray<V, N>>,
297 index: usize,
298) -> (res: &V)
299 requires
300 perm.ptr() == ptr,
301 perm.is_init(index as int),
302 ensures
303 res == perm.opt_value()[index as int].value(),
304 opens_invariants none
305 no_unwind
306{
307 unsafe { &*((ptr as *const V).add(index)) }
308}
309
310#[inline(always)]
312#[verifier::external_body]
313pub exec fn ptr_ref<V, const N: usize>(
314 ptr: *mut [V; N],
315 Tracked(perm): Tracked<&PointsToArray<V, N>>,
316) -> (res: &[V; N])
317 requires
318 perm.ptr() == ptr,
319 perm.is_init_all(),
320 ensures
321 forall|i: int| 0 <= i < N ==> #[trigger] res[i] == perm.opt_value()[i].value(),
322 opens_invariants none
323 no_unwind
324{
325 unsafe { &*ptr }
326}
327
328pub tracked struct PointsTo<V, const N: usize> {
330 points_to: PointsToArray<V, N>,
331 exposed: raw_ptr::IsExposed,
332 dealloc: Option<raw_ptr::Dealloc>,
333}
334
335broadcast use {
336 raw_ptr::group_raw_ptr_axioms,
337 set_lib::group_set_lib_default,
338 set::group_set_axioms,
339};
340
341impl<V, const N: usize> ArrayPtr<V, N> {
342 #[inline(always)]
344 #[vstd::contrib::auto_spec]
345 pub exec fn addr(&self) -> usize
346 returns
347 self.addr,
348 {
349 self.addr
350 }
351
352 #[inline(always)]
354 pub exec fn from_addr(addr: usize) -> (res: Self)
355 ensures
356 res.addr == addr,
357 res.index == 0,
358 {
359 Self { addr, index: 0, _type: PhantomData }
360 }
361
362 #[vstd::contrib::auto_spec]
363 pub exec fn add(self, off: usize) -> Self
364 requires
365 self.index + off
366 <= N ,
368 {
369 Self { addr: self.addr, index: (self.index + off) as usize, _type: PhantomData }
370 }
371}
372
373impl<V, const N: usize> PointsTo<V, N> {
374 pub closed spec fn addr(self) -> usize {
376 self.points_to.ptr()@.addr
377 }
378
379 pub open spec fn is_pptr(self, ptr: ArrayPtr<V, N>) -> bool {
381 ptr.addr == self.addr()
382 }
383
384 pub closed spec fn wf(self) -> bool {
388 &&& self.points_to.ptr()@.metadata == ()
390 &&& self.points_to.ptr()@.provenance == self.exposed.provenance()
391 &&& match self.dealloc {
392 Some(dealloc) => {
393 &&& dealloc.addr() == self.addr()
394 &&& dealloc.size() == layout::size_of::<[V; N]>()
395 &&& dealloc.align() == layout::align_of::<[V; N]>()
396 &&& dealloc.provenance() == self.exposed.provenance()
397 &&& layout::size_of::<[V; N]>() > 0
398 },
399 None => { layout::size_of::<[V; N]>() == 0 },
400 }
401 &&& self.addr() != 0
402 }
403
404 pub closed spec fn points_to(self) -> PointsToArray<V, N> {
405 self.points_to
406 }
407
408 pub open spec fn opt_value(self) -> [raw_ptr::MemContents<V>; N] {
409 self.points_to().opt_value()
410 }
411
412 pub open spec fn value(self) -> Seq<V>
413 recommends
414 self.is_init_all(),
415 {
416 self.points_to().value()
417 }
418
419 #[verifier::inline]
420 pub open spec fn is_init(self, index: int) -> bool {
421 self.points_to().is_init(index)
422 }
423
424 #[verifier::inline]
425 pub open spec fn is_uninit(self, index: int) -> bool {
426 !self.points_to().is_init(index)
427 }
428
429 #[verifier::inline]
430 pub open spec fn is_init_all(self) -> bool {
431 self.points_to().is_init_all()
432 }
433
434 #[verifier::inline]
435 pub open spec fn is_uninit_all(self) -> bool {
436 self.points_to().is_uninit_all()
437 }
438
439 pub proof fn is_nonnull(tracked self)
440 requires
441 self.wf(),
442 ensures
443 self.addr() != 0,
444 {
445 self.wf();
446 }
447
448 pub proof fn leak_contents(tracked &mut self, index: int)
449 requires
450 old(self).wf(),
451 ensures
452 self.wf(),
453 self.addr() == old(self).addr(),
454 self.is_uninit(index),
455 forall|i: int|
456 0 <= i < N && i != index ==> self.opt_value()[i] == old(self).opt_value()[i],
457 {
458 self.wf();
459 self.points_to.leak_contents(index);
460 }
461
462 pub proof fn is_disjoint<S, const M: usize>(&self, other: &PointsTo<S, M>)
463 ensures
464 self.addr() + layout::size_of::<[V; N]>() <= other.addr() || other.addr()
465 + layout::size_of::<[S; M]>() <= self.addr(),
466 {
467 self.points_to.is_disjoint(&other.points_to)
468 }
469
470 pub proof fn is_distinct<S, const M: usize>(&self, other: &PointsTo<S, M>)
471 requires
472 layout::size_of::<[V; N]>() != 0,
473 layout::size_of::<[S; M]>() != 0,
474 ensures
475 self.addr() != other.addr(),
476 {
477 self.points_to.is_disjoint(&other.points_to);
478 }
479}
480
481impl<V, const N: usize> PointsToArray<V, N> {
482 #[verifier::external_body]
483 pub proof fn into_array(tracked pt: raw_ptr::PointsTo<[V; N]>) -> (tracked res: PointsToArray<
484 V,
485 N,
486 >)
487 ensures
488 res@.ptr == pt@.ptr,
489 res@.value == mem_contents_wrap(pt@.opt_value),
490 {
491 Tracked::<PointsToArray<V, N>>::assume_new().get()
492 }
493
494 #[verifier::external_body]
495 pub proof fn into_ptr(tracked self) -> (tracked res: raw_ptr::PointsTo<[V; N]>)
496 ensures
497 res@.ptr == self@.ptr,
498 res@.opt_value == mem_contents_unwrap(self@.value),
499 {
500 Tracked::<raw_ptr::PointsTo<[V; N]>>::assume_new().get()
501 }
502}
503
504impl<V, const N: usize> Clone for ArrayPtr<V, N> {
505 fn clone(&self) -> (res: Self)
506 ensures
507 res === *self,
508 {
509 Self { ..*self }
510 }
511}
512
513impl<V, const N: usize> Copy for ArrayPtr<V, N> {
514
515}
516
517#[verifier::external_body]
518#[inline(always)]
519pub exec fn layout_for_array_is_valid<V: Sized, const N: usize>()
520 ensures
521 layout::valid_layout(
522 layout::size_of::<[V; N]>() as usize,
523 layout::align_of::<[V; N]>() as usize,
524 ),
525 layout::size_of::<[V; N]>() as usize as nat == layout::size_of::<[V; N]>(),
526 layout::align_of::<[V; N]>() as usize as nat == layout::align_of::<[V; N]>(),
527 opens_invariants none
528 no_unwind
529{
530}
531
532impl<V, const N: usize> ArrayPtr<V, N> {
533 pub exec fn empty() -> (res: (ArrayPtr<V, N>, Tracked<PointsTo<V, N>>))
534 requires
535 layout::size_of::<[V; N]>() > 0,
536 ensures
537 res.1@.wf(),
538 res.1@.is_pptr(res.0),
539 res.1@.is_uninit_all(),
540 {
541 layout_for_array_is_valid::<V, N>();
542 let (p, Tracked(raw_perm), Tracked(dealloc)) = raw_ptr::allocate(
543 core::mem::size_of::<[V; N]>(),
544 core::mem::align_of::<[V; N]>(),
545 );
546 let Tracked(exposed) = raw_ptr::expose_provenance(p);
547 let tracked ptr_perm = raw_perm.into_typed::<[V; N]>(p as usize);
548 proof {
549 ptr_perm.is_nonnull();
550 assert(ptr_perm.is_uninit());
551 }
552
553 let tracked arr_perm = PointsToArray::into_array(ptr_perm);
554 proof {
555 arr_perm.is_nonnull();
556 axiom_mem_contents_wrap_correctness(ptr_perm.opt_value(), arr_perm@.value);
557 assert(arr_perm.is_uninit_all());
558 }
559 let tracked pt = PointsTo { points_to: arr_perm, exposed, dealloc: Some(dealloc) };
560 proof {
561 assert(pt.is_uninit_all());
562 }
563 let ptr = ArrayPtr { addr: p as usize, index: 0, _type: PhantomData };
564 (ptr, Tracked(pt))
565 }
566
567 #[inline(always)]
568 pub exec fn make_as(&self, Tracked(perm): Tracked<&mut PointsTo<V, N>>, value: V) where V: Copy
569 requires
570 old(perm).wf(),
571 old(perm).is_pptr(*self),
572 old(perm).is_uninit_all(),
573 ensures
574 perm.wf(),
575 perm.is_pptr(*self),
576 perm.is_init_all(),
577 forall|i: int| 0 <= i < N ==> perm.opt_value()[i] == raw_ptr::MemContents::Init(value),
578 {
579 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
580
581 assert(perm.points_to().is_uninit_all());
582 ptr_mut_fill(ptr, Tracked(&mut perm.points_to), value);
583 }
584
585 pub exec fn new(dft: V) -> (res: (ArrayPtr<V, N>, Tracked<PointsTo<V, N>>)) where V: Copy
586 requires
587 layout::size_of::<[V; N]>() > 0,
588 ensures
589 res.1@.wf(),
590 res.1@.is_pptr(res.0),
591 forall|i: int|
592 0 <= i < N ==> #[trigger] res.1@.opt_value()[i] == raw_ptr::MemContents::Init(dft),
593 {
594 let (p, Tracked(perm)) = ArrayPtr::empty();
595 proof {
596 assert(perm.wf());
597 assert(perm.is_pptr(p));
598 assert(perm.is_uninit_all());
599 }
600 p.make_as(Tracked(&mut perm), dft);
601 (p, Tracked(perm))
602 }
603
604 pub exec fn free(self, Tracked(perm): Tracked<PointsTo<V, N>>)
605 requires
606 perm.wf(),
607 perm.is_pptr(self),
608 perm.is_uninit_all(),
609 {
610 if core::mem::size_of::<[V; N]>() == 0 {
611 return ;
612 }
613 assert(core::mem::size_of::<[V; N]>() > 0);
614 let ptr: *mut u8 = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
615 let tracked PointsTo { points_to, dealloc: dea, exposed } = perm;
616
617 proof {
618 assert(perm.is_uninit_all());
619 assert(points_to.is_uninit_all());
620 }
621 let tracked perm_ptr: raw_ptr::PointsTo<[V; N]> = points_to.into_ptr();
622 proof {
623 axiom_mem_contents_unwrap_uninit_correctness(points_to@.value, perm_ptr.opt_value());
624 assert(perm_ptr.is_uninit());
625 }
626 let tracked perm_raw = perm_ptr.into_raw();
627
628 raw_ptr::deallocate(
629 ptr,
630 core::mem::size_of::<[V; N]>(),
631 core::mem::align_of::<[V; N]>(),
632 Tracked(perm_raw),
633 Tracked(dea.tracked_unwrap()),
634 );
635 }
636
637 #[inline(always)]
641 pub exec fn insert(&self, Tracked(perm): Tracked<&mut PointsTo<V, N>>, value: V)
642 requires
643 old(perm).wf(),
644 old(perm).is_pptr(*self),
645 old(perm).is_uninit(self.index as int),
646 self.index < N,
647 ensures
648 perm.wf(),
649 perm.is_pptr(*self),
650 perm.is_init(self.index as int),
651 forall|i: int|
652 0 <= i < N && i != self.index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
653 perm.opt_value()[self.index as int] == raw_ptr::MemContents::Init(value),
654 {
655 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
656
657 assert(perm.points_to().is_uninit(self.index as int));
658 ptr_mut_write_at(ptr, Tracked(&mut perm.points_to), self.index, value);
659 }
660
661 #[inline(always)]
666 pub exec fn take_at(&self, Tracked(perm): Tracked<&mut PointsTo<V, N>>) -> (res: V) where
667 V: Copy,
668
669 requires
670 old(perm).wf(),
671 old(perm).is_pptr(*self),
672 old(perm).is_init(self.index as int),
673 self.index < N,
674 ensures
675 perm.wf(),
676 perm.is_pptr(*self),
677 perm.is_uninit(self.index as int),
678 forall|i: int|
679 0 <= i < N && i != self.index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
680 res == old(perm).opt_value()[self.index as int].value(),
681 {
682 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
683
684 assert(perm.points_to().is_init(self.index as int));
685 ptr_mut_read_at(ptr, Tracked(&mut perm.points_to), self.index)
686 }
687
688 #[inline(always)]
693 pub exec fn take_all(&self, Tracked(perm): Tracked<&mut PointsTo<V, N>>) -> (res: [V; N])
694 requires
695 old(perm).wf(),
696 old(perm).is_pptr(*self),
697 old(perm).is_init_all(),
698 ensures
699 perm.wf(),
700 perm.is_pptr(*self),
701 perm.is_uninit_all(),
702 res@ == old(perm).value(),
703 {
704 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
705
706 assert(perm.points_to().is_init_all());
707 ptr_mut_read_all(ptr, Tracked(&mut perm.points_to))
708 }
709
710 #[inline(always)]
715 pub exec fn into_inner(self, Tracked(perm): Tracked<PointsTo<V, N>>) -> (res: [V; N])
716 requires
717 perm.wf(),
718 perm.is_pptr(self),
719 perm.is_init_all(),
720 ensures
721 res@ == perm.value(),
722 {
723 let tracked mut perm = perm;
724 let res = self.take_all(Tracked(&mut perm));
725 self.free(Tracked(perm));
726 res
727 }
728
729 #[inline(always)]
734 pub exec fn update(
735 &self,
736 Tracked(perm): Tracked<&mut PointsTo<V, N>>,
737 index: usize,
738 value: V,
739 ) -> (res: V) where V: Copy
740 requires
741 old(perm).wf(),
742 old(perm).is_pptr(*self),
743 old(perm).is_init(index as int),
744 index < N,
745 ensures
746 perm.wf(),
747 perm.is_pptr(*self),
748 perm.is_init(index as int),
749 forall|i: int|
750 0 <= i < N && i != index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
751 perm.opt_value()[index as int] == raw_ptr::MemContents::Init(value),
752 res == old(perm).opt_value()[index as int].value(),
753 {
754 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
755
756 assert(perm.points_to().is_init(index as int));
757 let res = ptr_mut_read_at(ptr, Tracked(&mut perm.points_to), index);
758 ptr_mut_write_at(ptr, Tracked(&mut perm.points_to), index, value);
759 res
760 }
761
762 #[inline(always)]
770 pub exec fn borrow_at<'a>(
771 &self,
772 Tracked(perm): Tracked<&'a PointsTo<V, N>>,
773 index: usize,
774 ) -> (res: &'a V)
775 requires
776 perm.wf(),
777 perm.is_pptr(*self),
778 perm.is_init(index as int),
779 index < N,
780 ensures
781 res == perm.opt_value()[index as int].value(),
782 {
783 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
784
785 assert(perm.points_to().is_init(index as int));
786 ptr_ref_at(ptr, Tracked(&perm.points_to), index)
787 }
788
789 #[inline(always)]
797 pub exec fn borrow<'a>(&self, Tracked(perm): Tracked<&'a PointsTo<V, N>>) -> (res: &'a [V; N])
798 requires
799 perm.wf(),
800 perm.is_pptr(*self),
801 perm.is_init_all(),
802 ensures
803 forall|i: int| 0 <= i < N ==> #[trigger] res[i] == perm.opt_value()[i].value(),
804 {
805 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
806
807 assert(perm.points_to().is_init_all());
808 ptr_ref(ptr, Tracked(&perm.points_to))
809 }
810
811 #[inline(always)]
814 pub exec fn overwrite(
815 &self,
816 Tracked(perm): Tracked<&mut PointsTo<V, N>>,
817 index: usize,
818 value: V,
819 )
820 requires
821 old(perm).wf(),
822 old(perm).is_pptr(*self),
823 index < N,
824 ensures
825 perm.wf(),
826 perm.is_pptr(*self),
827 perm.is_init(index as int),
828 forall|i: int|
829 0 <= i < N && i != index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
830 perm.opt_value()[index as int] == raw_ptr::MemContents::Init(value),
831 opens_invariants none
832 no_unwind
833 {
834 proof {
835 perm.leak_contents(index as int);
836 }
837 assert(perm.is_uninit(index as int));
838 let ptr: *mut [V; N] = raw_ptr::with_exposed_provenance(self.addr, Tracked(perm.exposed));
839
840 ptr_mut_write_at(ptr, Tracked(&mut perm.points_to), index, value);
841 }
842
843 #[verifier::external_body]
844 pub proof fn tracked_overwrite(
845 tracked &self,
846 tracked perm: &mut PointsTo<V, N>,
847 tracked index: usize,
848 tracked value: V,
849 )
850 requires
851 old(perm).wf(),
852 old(perm).is_pptr(*self),
853 index < N,
854 ensures
855 perm.wf(),
856 perm.is_pptr(*self),
857 perm.is_init(index as int),
858 forall|i: int|
859 0 <= i < N && i != index ==> perm.opt_value()[i] == old(perm).opt_value()[i],
860 perm.opt_value()[index as int] == raw_ptr::MemContents::Init(value),
861 {
862 self.overwrite(Tracked(perm), index, value);
863 }
864
865 #[inline(always)]
870 pub exec fn get(&self, Tracked(perm): Tracked<&PointsTo<V, N>>, index: usize) -> (res: V) where
871 V: Copy,
872
873 requires
874 perm.wf(),
875 perm.is_pptr(*self),
876 perm.is_init(index as int),
877 index < N,
878 ensures
879 res == perm.opt_value()[index as int].value(),
880 {
881 *self.borrow_at(Tracked(perm), index)
882 }
883}
884
885}