1use core::marker::PhantomData;
2
3use vstd::prelude::*;
4
5use vstd::{
6 atomic::*,
7 seq_lib::*,
8 set_lib::*,
9 simple_pptr::*,
10 std_specs::convert::{FromSpec, FromSpecImpl},
11};
12use vstd_extra::{
13 cast_ptr::{Repr, ReprPtr},
14 ownership::*,
15};
16
17use crate::specs::{
18 arch::MAX_NR_PAGES,
19 mm::frame::{
20 mapping::{frame_to_index, max_meta_slots},
21 meta_owners::*,
22 meta_region_owners::MetaRegionOwners,
23 unique::UniqueFrameOwner,
24 },
25};
26
27use crate::mm::{
28 Paddr,
29 frame::{
30 AnyFrameMeta, CursorMut, Link, LinkedList, MetaSlot,
31 meta::{
32 META_SLOT_SIZE, REF_COUNT_UNIQUE,
33 mapping::{frame_to_meta, meta_to_frame},
34 },
35 },
36 kspace::FRAME_METADATA_RANGE,
37};
38
39use super::*;
40
41verus! {
42
43pub struct MetaSlotSmall;
44
45pub struct StoredLink {
47 pub next: Option<Paddr>,
48 pub prev: Option<Paddr>,
49 pub slot: MetaSlotSmall,
50}
51
52pub tracked struct LinkInnerPerms<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
53 pub storage: <M as Repr<MetaSlotSmall>>::Perm,
54 pub ghost next_ptr: Option<PPtr<MetaSlot>>,
55 pub ghost prev_ptr: Option<PPtr<MetaSlot>>,
56}
57
58impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Repr<MetaSlotStorage> for Link<M> {
59 type Perm = LinkInnerPerms<M>;
60
61 open spec fn wf(r: MetaSlotStorage, perm: LinkInnerPerms<M>) -> bool {
62 match r {
63 MetaSlotStorage::FrameLink(link) => {
64 &&& M::wf(link.slot, perm.storage)
65 &&& (link.next is Some) == (perm.next_ptr is Some)
66 &&& (link.prev is Some) == (perm.prev_ptr is Some)
67 &&& link.next is Some ==> link.next->0 == perm.next_ptr->0.addr()
68 &&& link.prev is Some ==> link.prev->0 == perm.prev_ptr->0.addr()
69 },
70 _ => false,
71 }
72 }
73
74 open spec fn to_repr_spec(self, perm: LinkInnerPerms<M>) -> (
75 MetaSlotStorage,
76 LinkInnerPerms<M>,
77 ) {
78 let (slot, storage) = self.meta.to_repr_spec(perm.storage);
79 (
80 MetaSlotStorage::FrameLink(
81 StoredLink {
82 next: match self.next {
83 Some(ptr) => Some(ptr.ptr.addr()),
84 None => None,
85 },
86 prev: match self.prev {
87 Some(ptr) => Some(ptr.ptr.addr()),
88 None => None,
89 },
90 slot,
91 },
92 ),
93 LinkInnerPerms {
94 storage,
95 next_ptr: match self.next {
96 Some(ptr) => Some(ptr.ptr),
97 None => None,
98 },
99 prev_ptr: match self.prev {
100 Some(ptr) => Some(ptr.ptr),
101 None => None,
102 },
103 },
104 )
105 }
106
107 #[verifier::external_body]
108 fn to_repr(self, Tracked(perm): Tracked<&mut LinkInnerPerms<M>>) -> MetaSlotStorage {
109 unimplemented!()
110 }
111
112 open spec fn from_repr_spec(r: MetaSlotStorage, perm: LinkInnerPerms<M>) -> Self {
113 match r {
114 MetaSlotStorage::FrameLink(link) => Link {
115 next: match link.next {
116 Some(addr) => Some(ReprPtr { ptr: perm.next_ptr->0, _T: PhantomData }),
117 None => None,
118 },
119 prev: match link.prev {
120 Some(addr) => Some(ReprPtr { ptr: perm.prev_ptr->0, _T: PhantomData }),
121 None => None,
122 },
123 meta: M::from_repr_spec(link.slot, perm.storage),
124 },
125 _ => Link {
126 next: None,
127 prev: None,
128 meta: M::from_repr_spec(MetaSlotSmall, perm.storage),
129 },
130 }
131 }
132
133 #[verifier::external_body]
134 fn from_repr(r: MetaSlotStorage, Tracked(perm): Tracked<&LinkInnerPerms<M>>) -> Self {
135 unimplemented!()
136 }
137
138 #[verifier::external_body]
139 fn from_borrowed<'a>(
140 r: &'a MetaSlotStorage,
141 Tracked(perm): Tracked<&'a LinkInnerPerms<M>>,
142 ) -> &'a Self {
143 unimplemented!()
144 }
145
146 proof fn from_to_repr(self, perm: LinkInnerPerms<M>) {
147 <M as Repr<MetaSlotSmall>>::from_to_repr(self.meta, perm.storage);
148 }
149
150 proof fn to_from_repr(r: MetaSlotStorage, perm: LinkInnerPerms<M>) {
151 match r {
152 MetaSlotStorage::FrameLink(link) => {
153 M::to_from_repr(link.slot, perm.storage);
154 },
155 _ => {
156 assert(false);
157 },
158 }
159 }
160
161 proof fn to_repr_wf(self, perm: LinkInnerPerms<M>) {
162 <M as Repr<MetaSlotSmall>>::to_repr_wf(self.meta, perm.storage);
163 }
164}
165
166pub ghost struct LinkModel {
167 pub paddr: Paddr,
168}
169
170impl Inv for LinkModel {
171 open spec fn inv(self) -> bool {
172 true
173 }
174}
175
176pub tracked struct LinkOwner {
177 pub ghost paddr: Paddr,
178 pub ghost in_list: u64,
179}
180
181impl Inv for LinkOwner {
182 open spec fn inv(self) -> bool {
183 true
184 }
185}
186
187impl View for LinkOwner {
188 type V = LinkModel;
189
190 open spec fn view(&self) -> Self::V {
191 LinkModel { paddr: self.paddr }
192 }
193}
194
195impl InvView for LinkOwner {
196 proof fn view_preserves_inv(self) {
197 }
198}
199
200impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for Link<M> {
201 type Owner = LinkOwner;
202
203 open spec fn wf(self, owner: Self::Owner) -> bool {
204 true
205 }
210}
211
212pub ghost struct LinkedListModel {
213 pub list: Seq<LinkModel>,
214}
215
216impl LinkedListModel {
217 pub open spec fn front(self) -> Option<LinkModel> {
218 if self.list.len() > 0 {
219 Some(self.list[0])
220 } else {
221 None
222 }
223 }
224
225 pub open spec fn back(self) -> Option<LinkModel> {
226 if self.list.len() > 0 {
227 Some(self.list[self.list.len() - 1])
228 } else {
229 None
230 }
231 }
232}
233
234impl Inv for LinkedListModel {
235 open spec fn inv(self) -> bool {
236 true
237 }
238}
239
240pub tracked struct LinkedListOwner<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
241 pub list: Seq<LinkOwner>,
242 pub ghost list_id: u64,
243 pub ghost _marker: core::marker::PhantomData<M>,
244}
245
246impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Inv for LinkedListOwner<M> {
247 open spec fn inv(self) -> bool {
248 &&& self.list.len() > 0 ==> self.list_id != 0
252 &&& forall|i: int| 0 <= i < self.list.len() ==> self.inv_at(i)
253 }
254}
255
256impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedListOwner<M> {
257 pub open spec fn inv_at(self, i: int) -> bool {
262 &&& self.list[i].inv()
263 &&& self.list[i].in_list == self.list_id
264 }
265
266 pub open spec fn slot_index_at(self, i: int) -> int {
268 frame_to_index(meta_to_frame(self.list[i].paddr))
269 }
270
271 pub open spec fn meta_perm_of(
275 self,
276 regions: MetaRegionOwners,
277 i: int,
278 ) -> vstd_extra::cast_ptr::PointsTo<MetaSlot, Metadata<Link<M>>> {
279 let idx = self.slot_index_at(i);
280 vstd_extra::cast_ptr::PointsTo::new_spec(
281 regions.slots[idx],
282 regions.slot_owners[idx].inner_perms,
283 )
284 }
285
286 #[verifier::opaque]
293 pub open spec fn relate_region_at(self, regions: MetaRegionOwners, i: int) -> bool {
294 let idx = self.slot_index_at(i);
295 let perm = self.meta_perm_of(regions, i);
296 &&& regions.slots.contains_key(idx)
297 &&& regions.slot_owners.contains_key(idx)
298 &&& perm.addr() == self.list[i].paddr
299 &&& perm.points_to.addr() == self.list[i].paddr
300 &&& perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
301 &&& regions.slot_owners[idx].usage is Frame
302 &&& perm.wf(&perm.inner_perms)
303 &&& perm.addr() % META_SLOT_SIZE == 0
304 &&& FRAME_METADATA_RANGE.start <= perm.addr() < FRAME_METADATA_RANGE.start + MAX_NR_PAGES
305 * META_SLOT_SIZE
306 &&& perm.is_init()
307 &&& perm.value().metadata.wf(self.list[i])
308 &&& i == 0 <==> perm.value().metadata.prev is None
309 &&& i == self.list.len() - 1 <==> perm.value().metadata.next is None
310 &&& 0 < i ==> {
311 &&& perm.value().metadata.prev is Some
312 &&& perm.value().metadata.prev->0.addr() == self.meta_perm_of(regions, i - 1).addr()
313 &&& perm.value().metadata.prev->0.ptr == self.meta_perm_of(
314 regions,
315 i - 1,
316 ).points_to.pptr()
317 }
318 &&& i < self.list.len() - 1 ==> {
319 &&& perm.value().metadata.next is Some
320 &&& perm.value().metadata.next->0.addr() == self.meta_perm_of(regions, i + 1).addr()
321 &&& perm.value().metadata.next->0.ptr == self.meta_perm_of(
322 regions,
323 i + 1,
324 ).points_to.pptr()
325 }
326 &&& self.list[i].inv()
327 &&& self.list[i].in_list == self.list_id
328 }
329
330 pub open spec fn relate_region(self, regions: MetaRegionOwners) -> bool {
335 &&& forall|i: int|
336 #![trigger self.list[i]]
337 0 <= i < self.list.len() ==> self.relate_region_at(regions, i)
338 &&& forall|i: int, j: int|
339 #![trigger self.slot_index_at(i), self.slot_index_at(j)]
340 0 <= i < self.list.len() && 0 <= j < self.list.len() && i != j ==> self.slot_index_at(i)
341 != self.slot_index_at(j)
342 &&& self.list.len() > 0 ==> self.list_id != 0
343 }
344
345 pub proof fn length_le_max_meta_slots(self, regions: MetaRegionOwners)
352 requires
353 self.relate_region(regions),
354 regions.inv(),
355 ensures
356 self.list.len() <= max_meta_slots(),
357 {
358 let idxs = Seq::new(self.list.len(), |i: int| self.slot_index_at(i));
359
360 idxs.unique_seq_to_set();
361
362 let bound = set_int_range(0, max_meta_slots());
363 assert(idxs.to_set().subset_of(bound)) by {
364 assert forall|x: int|
365 #![trigger idxs.to_set().contains(x)]
366 idxs.to_set().contains(x) implies bound.contains(x) by {
367 let i = choose|i: int| 0 <= i < idxs.len() && idxs[i] == x;
368 self.relate_region_at_facts(regions, i);
369 }
371 }
372 lemma_int_range(0, max_meta_slots());
373 lemma_len_subset(idxs.to_set(), bound);
374 }
375
376 pub proof fn length_lt_usize_max(self, regions: MetaRegionOwners)
381 requires
382 self.relate_region(regions),
383 regions.inv(),
384 ensures
385 self.list.len() < usize::MAX,
386 {
387 self.length_le_max_meta_slots(regions);
388 }
389
390 pub proof fn relate_region_at_facts(self, regions: MetaRegionOwners, i: int)
395 requires
396 self.relate_region_at(regions, i),
397 ensures
398 ({
399 let idx = self.slot_index_at(i);
400 let perm = self.meta_perm_of(regions, i);
401 &&& regions.slots.contains_key(idx)
402 &&& regions.slot_owners.contains_key(idx)
403 &&& perm.addr() == self.list[i].paddr
404 &&& perm.points_to.addr() == self.list[i].paddr
405 &&& perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
406 &&& regions.slot_owners[idx].usage is Frame
407 &&& perm.wf(&perm.inner_perms)
408 &&& perm.addr() % META_SLOT_SIZE == 0
409 &&& FRAME_METADATA_RANGE.start <= perm.addr() < FRAME_METADATA_RANGE.start
410 + MAX_NR_PAGES * META_SLOT_SIZE
411 &&& perm.is_init()
412 &&& perm.value().metadata.wf(self.list[i])
413 &&& (i == 0 <==> perm.value().metadata.prev is None)
414 &&& (i == self.list.len() - 1 <==> perm.value().metadata.next is None)
415 &&& (0 < i ==> {
416 &&& perm.value().metadata.prev is Some
417 &&& perm.value().metadata.prev->0.addr() == self.meta_perm_of(
418 regions,
419 i - 1,
420 ).addr()
421 &&& perm.value().metadata.prev->0.ptr == self.meta_perm_of(
422 regions,
423 i - 1,
424 ).points_to.pptr()
425 })
426 &&& (i < self.list.len() - 1 ==> {
427 &&& perm.value().metadata.next is Some
428 &&& perm.value().metadata.next->0.addr() == self.meta_perm_of(
429 regions,
430 i + 1,
431 ).addr()
432 &&& perm.value().metadata.next->0.ptr == self.meta_perm_of(
433 regions,
434 i + 1,
435 ).points_to.pptr()
436 })
437 &&& self.list[i].inv()
438 &&& self.list[i].in_list == self.list_id
439 }),
440 {
441 reveal(LinkedListOwner::relate_region_at);
442 }
443
444 pub proof fn relate_region_at_from_clauses(self, regions: MetaRegionOwners, i: int)
449 requires
450 ({
451 let idx = self.slot_index_at(i);
452 let perm = self.meta_perm_of(regions, i);
453 &&& regions.slots.contains_key(idx)
454 &&& regions.slot_owners.contains_key(idx)
455 &&& perm.addr() == self.list[i].paddr
456 &&& perm.points_to.addr() == self.list[i].paddr
457 &&& perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
458 &&& regions.slot_owners[idx].usage is Frame
459 &&& perm.wf(&perm.inner_perms)
460 &&& perm.addr() % META_SLOT_SIZE == 0
461 &&& FRAME_METADATA_RANGE.start <= perm.addr() < FRAME_METADATA_RANGE.start
462 + MAX_NR_PAGES * META_SLOT_SIZE
463 &&& perm.is_init()
464 &&& perm.value().metadata.wf(self.list[i])
465 &&& (i == 0 <==> perm.value().metadata.prev is None)
466 &&& (i == self.list.len() - 1 <==> perm.value().metadata.next is None)
467 &&& (0 < i ==> {
468 &&& perm.value().metadata.prev is Some
469 &&& perm.value().metadata.prev->0.addr() == self.meta_perm_of(
470 regions,
471 i - 1,
472 ).addr()
473 &&& perm.value().metadata.prev->0.ptr == self.meta_perm_of(
474 regions,
475 i - 1,
476 ).points_to.pptr()
477 })
478 &&& (i < self.list.len() - 1 ==> {
479 &&& perm.value().metadata.next is Some
480 &&& perm.value().metadata.next->0.addr() == self.meta_perm_of(
481 regions,
482 i + 1,
483 ).addr()
484 &&& perm.value().metadata.next->0.ptr == self.meta_perm_of(
485 regions,
486 i + 1,
487 ).points_to.pptr()
488 })
489 &&& self.list[i].inv()
490 &&& self.list[i].in_list == self.list_id
491 }),
492 ensures
493 self.relate_region_at(regions, i),
494 {
495 reveal(LinkedListOwner::relate_region_at);
496 }
497
498 pub proof fn relate_region_preserved_external_change(
506 self,
507 regions1: MetaRegionOwners,
508 regions2: MetaRegionOwners,
509 )
510 requires
511 self.relate_region(regions1),
512 regions2.slots == regions1.slots,
513 forall|i: int|
514 #![trigger self.list[i]]
515 0 <= i < self.list.len() ==> {
516 let idx = self.slot_index_at(i);
517 &&& regions2.slot_owners.contains_key(idx)
518 &&& regions2.slot_owners[idx] == regions1.slot_owners[idx]
519 },
520 ensures
521 self.relate_region(regions2),
522 {
523 let llen = self.list.len() as int;
524 assert forall|k: int|
525 #![trigger self.relate_region_at(regions2, k)]
526 0 <= k < llen implies self.relate_region_at(regions2, k) by {
527 let _ = self.list[k];
528 self.relate_region_at_facts(regions1, k);
529 self.relate_region_at_from_clauses(regions2, k);
530 }
531 }
532
533 #[verifier::spinoff_prover]
544 pub proof fn pop_preserves_relate_region(
545 old: LinkedListOwner<M>,
546 r0: MetaRegionOwners,
547 new: LinkedListOwner<M>,
548 fr: MetaRegionOwners,
549 n: int,
550 )
551 requires
552 0 <= n < old.list.len(),
553 old.relate_region(r0),
554 new.list == old.list.remove(n),
555 new.list_id == old.list_id,
556 forall|p: int|
557 #![trigger old.slot_index_at(p)]
558 (0 <= p < old.list.len() && p != n) ==> ({
559 let i = old.slot_index_at(p);
560 let fp = vstd_extra::cast_ptr::PointsTo::<
561 MetaSlot,
562 Metadata<Link<M>>,
563 >::new_spec(fr.slots[i], fr.slot_owners[i].inner_perms);
564 &&& fr.slots.contains_key(i)
565 &&& fr.slot_owners.contains_key(i)
566 &&& fp.addr() == old.list[p].paddr
567 &&& fp.points_to.addr() == old.list[p].paddr
568 &&& fp.points_to.pptr() == r0.slots[i].pptr()
569 &&& fp.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
570 &&& fr.slot_owners[i].usage is Frame
571 &&& fp.wf(&fp.inner_perms)
572 &&& fp.addr() % META_SLOT_SIZE == 0
573 &&& FRAME_METADATA_RANGE.start <= fp.addr() < FRAME_METADATA_RANGE.start
574 + MAX_NR_PAGES * META_SLOT_SIZE
575 &&& fp.is_init()
576 &&& (p == n - 1 ==> fp.value().metadata.next == old.meta_perm_of(
577 r0,
578 n,
579 ).value().metadata.next)
580 &&& (p != n - 1 ==> fp.value().metadata.next == old.meta_perm_of(
581 r0,
582 p,
583 ).value().metadata.next)
584 &&& (p == n + 1 ==> fp.value().metadata.prev == old.meta_perm_of(
585 r0,
586 n,
587 ).value().metadata.prev)
588 &&& (p != n + 1 ==> fp.value().metadata.prev == old.meta_perm_of(
589 r0,
590 p,
591 ).value().metadata.prev)
592 }),
593 ensures
594 new.relate_region(fr),
595 {
596 let nlen = new.list.len() as int;
597
598 assert forall|k: int| #![trigger new.slot_index_at(k)] 0 <= k < nlen implies {
599 let p = if k < n {
600 k
601 } else {
602 k + 1
603 };
604 &&& new.list[k] == old.list[p]
605 &&& new.slot_index_at(k) == old.slot_index_at(p)
606 } by {}
607
608 assert forall|a: int, b: int|
609 #![trigger new.slot_index_at(a), new.slot_index_at(b)]
610 0 <= a < nlen && 0 <= b < nlen && a != b implies new.slot_index_at(a)
611 != new.slot_index_at(b) by {
612 let pa = if a < n {
613 a
614 } else {
615 a + 1
616 };
617 let pb = if b < n {
618 b
619 } else {
620 b + 1
621 };
622 }
623
624 assert forall|m: int| #![trigger new.meta_perm_of(fr, m)] 0 <= m < nlen implies {
625 let pm = if m < n {
626 m
627 } else {
628 m + 1
629 };
630 &&& new.meta_perm_of(fr, m).addr() == old.meta_perm_of(r0, pm).addr()
631 &&& new.meta_perm_of(fr, m).points_to.pptr() == old.meta_perm_of(
632 r0,
633 pm,
634 ).points_to.pptr()
635 } by {
636 let pm = if m < n {
637 m
638 } else {
639 m + 1
640 };
641 old.relate_region_at_facts(r0, pm);
642 }
643
644 assert forall|k: int|
645 #![trigger new.relate_region_at(fr, k)]
646 0 <= k < nlen implies new.relate_region_at(fr, k) by {
647 let p = if k < n {
648 k
649 } else {
650 k + 1
651 };
652 let _ = old.list[p];
653 old.relate_region_at_facts(r0, p);
654 let _ = old.list[n];
655 old.relate_region_at_facts(r0, n);
656 if p - 1 >= 0 {
657 let _ = old.list[p - 1];
658 old.relate_region_at_facts(r0, p - 1);
659 }
660 if p + 1 < old.list.len() {
661 let _ = old.list[p + 1];
662 old.relate_region_at_facts(r0, p + 1);
663 }
664 if n - 1 >= 0 {
665 let _ = old.list[n - 1];
666 old.relate_region_at_facts(r0, n - 1);
667 }
668 if n + 1 < old.list.len() {
669 old.relate_region_at_facts(r0, n + 1);
670 }
671 new.relate_region_at_from_clauses(fr, k);
672 }
673
674 }
675
676 #[verifier::spinoff_prover]
688 #[verifier::rlimit(60)]
689 pub proof fn insert_preserves_relate_region(
690 old: LinkedListOwner<M>,
691 r0: MetaRegionOwners,
692 new: LinkedListOwner<M>,
693 fr: MetaRegionOwners,
694 n: int,
695 link: LinkOwner,
696 )
697 requires
698 0 <= n <= old.list.len(),
699 old.relate_region(r0),
700 new.list == old.list.insert(n, link),
701 new.list_id != 0,
702 old.list.len() > 0 ==> new.list_id == old.list_id,
703 link.in_list == new.list_id,
704 forall|p: int|
705 #![trigger old.slot_index_at(p)]
706 (0 <= p < old.list.len()) ==> old.slot_index_at(p) != new.slot_index_at(n),
707 ({
708 let ins = new.slot_index_at(n);
709 let fpn = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
710 fr.slots[ins],
711 fr.slot_owners[ins].inner_perms,
712 );
713 &&& fr.slots.contains_key(ins)
714 &&& fr.slot_owners.contains_key(ins)
715 &&& fpn.addr() == link.paddr
716 &&& fpn.points_to.addr() == link.paddr
717 &&& fpn.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
718 &&& fr.slot_owners[ins].usage is Frame
719 &&& fpn.wf(&fpn.inner_perms)
720 &&& fpn.addr() % META_SLOT_SIZE == 0
721 &&& FRAME_METADATA_RANGE.start <= fpn.addr() < FRAME_METADATA_RANGE.start
722 + MAX_NR_PAGES * META_SLOT_SIZE
723 &&& fpn.is_init()
724 &&& (n == 0 <==> fpn.value().metadata.prev is None)
725 &&& (n == old.list.len() <==> fpn.value().metadata.next is None)
726 &&& (n > 0 ==> {
727 &&& fpn.value().metadata.prev is Some
728 &&& fpn.value().metadata.prev->0.addr() == old.list[n - 1].paddr
729 &&& fpn.value().metadata.prev->0.ptr == r0.slots[old.slot_index_at(
730 n - 1,
731 )].pptr()
732 })
733 &&& (n < old.list.len() ==> {
734 &&& fpn.value().metadata.next is Some
735 &&& fpn.value().metadata.next->0.addr() == old.list[n].paddr
736 &&& fpn.value().metadata.next->0.ptr == r0.slots[old.slot_index_at(n)].pptr()
737 })
738 }),
739 forall|p: int|
740 #![trigger old.slot_index_at(p)]
741 (0 <= p < old.list.len()) ==> ({
742 let i = old.slot_index_at(p);
743 let ins = new.slot_index_at(n);
744 let fp = vstd_extra::cast_ptr::PointsTo::<
745 MetaSlot,
746 Metadata<Link<M>>,
747 >::new_spec(fr.slots[i], fr.slot_owners[i].inner_perms);
748 &&& fr.slots.contains_key(i)
749 &&& fr.slot_owners.contains_key(i)
750 &&& fp.addr() == old.list[p].paddr
751 &&& fp.points_to.addr() == old.list[p].paddr
752 &&& fp.points_to.pptr() == r0.slots[i].pptr()
753 &&& fp.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
754 &&& fr.slot_owners[i].usage is Frame
755 &&& fp.wf(&fp.inner_perms)
756 &&& fp.addr() % META_SLOT_SIZE == 0
757 &&& FRAME_METADATA_RANGE.start <= fp.addr() < FRAME_METADATA_RANGE.start
758 + MAX_NR_PAGES * META_SLOT_SIZE
759 &&& fp.is_init()
760 &&& (p == n - 1 ==> {
761 &&& fp.value().metadata.next is Some
762 &&& fp.value().metadata.next->0.addr() == link.paddr
763 &&& fp.value().metadata.next->0.ptr == fr.slots[ins].pptr()
764 })
765 &&& (p != n - 1 ==> fp.value().metadata.next == old.meta_perm_of(
766 r0,
767 p,
768 ).value().metadata.next)
769 &&& (p == n ==> {
770 &&& fp.value().metadata.prev is Some
771 &&& fp.value().metadata.prev->0.addr() == link.paddr
772 &&& fp.value().metadata.prev->0.ptr == fr.slots[ins].pptr()
773 })
774 &&& (p != n ==> fp.value().metadata.prev == old.meta_perm_of(
775 r0,
776 p,
777 ).value().metadata.prev)
778 }),
779 ensures
780 new.relate_region(fr),
781 {
782 let nlen = new.list.len() as int;
783 let ins = new.slot_index_at(n);
784
785 assert forall|k: int| #![trigger new.slot_index_at(k)] 0 <= k < nlen implies ({
786 &&& (k < n ==> new.list[k] == old.list[k] && new.slot_index_at(k) == old.slot_index_at(
787 k,
788 ))
789 &&& (k == n ==> new.list[k] == link && new.slot_index_at(k) == ins)
790 &&& (k > n ==> new.list[k] == old.list[k - 1] && new.slot_index_at(k)
791 == old.slot_index_at(k - 1))
792 }) by {}
793
794 assert forall|a: int, b: int|
795 #![trigger new.slot_index_at(a), new.slot_index_at(b)]
796 0 <= a < nlen && 0 <= b < nlen && a != b implies new.slot_index_at(a)
797 != new.slot_index_at(b) by {}
798
799 assert forall|m: int| #![trigger new.meta_perm_of(fr, m)] 0 <= m < nlen implies ({
800 &&& (m < n ==> new.meta_perm_of(fr, m).addr() == old.meta_perm_of(r0, m).addr()
801 && new.meta_perm_of(fr, m).points_to.pptr() == old.meta_perm_of(
802 r0,
803 m,
804 ).points_to.pptr())
805 &&& (m > n ==> new.meta_perm_of(fr, m).addr() == old.meta_perm_of(r0, m - 1).addr()
806 && new.meta_perm_of(fr, m).points_to.pptr() == old.meta_perm_of(
807 r0,
808 m - 1,
809 ).points_to.pptr())
810 }) by {
811 if m < n {
812 old.relate_region_at_facts(r0, m);
813 }
814 if m > n {
815 old.relate_region_at_facts(r0, m - 1);
816 }
817 }
818
819 assert forall|k: int|
820 #![trigger new.relate_region_at(fr, k)]
821 0 <= k < nlen implies new.relate_region_at(fr, k) by {
822 if k < n {
823 let _ = old.list[k];
824 old.relate_region_at_facts(r0, k);
825 }
826 if k > n {
827 let _ = old.list[k - 1];
828 old.relate_region_at_facts(r0, k - 1);
829 }
830 if n - 1 >= 0 && n - 1 < old.list.len() {
831 let _ = old.list[n - 1];
832 old.relate_region_at_facts(r0, n - 1);
833 }
834 if n >= 0 && n < old.list.len() {
835 let _ = old.list[n];
836 old.relate_region_at_facts(r0, n);
837 }
838 new.relate_region_at_from_clauses(fr, k);
839 }
840
841 }
843
844 pub open spec fn view_helper(owners: Seq<LinkOwner>) -> Seq<LinkModel>
845 decreases owners.len(),
846 {
847 if owners.len() == 0 {
848 Seq::<LinkModel>::empty()
849 } else {
850 seq![owners[0].view()].add(Self::view_helper(owners.remove(0)))
851 }
852 }
853
854 pub proof fn view_preserves_len(owners: Seq<LinkOwner>)
855 ensures
856 Self::view_helper(owners).len() == owners.len(),
857 decreases owners.len(),
858 {
859 if owners.len() > 0 {
860 Self::view_preserves_len(owners.remove(0))
861 }
862 }
863
864 pub proof fn view_helper_index(owners: Seq<LinkOwner>, i: int)
866 requires
867 0 <= i < owners.len(),
868 ensures
869 Self::view_helper(owners)[i] == owners[i].view(),
870 decreases owners.len(),
871 {
872 Self::view_preserves_len(owners);
873 if i > 0 {
874 Self::view_helper_index(owners.remove(0), i - 1);
875 }
876 }
877
878 pub proof fn view_helper_remove(owners: Seq<LinkOwner>, i: int)
881 requires
882 0 <= i < owners.len(),
883 ensures
884 Self::view_helper(owners.remove(i)) == Self::view_helper(owners).remove(i),
885 {
886 Self::view_preserves_len(owners);
887 Self::view_preserves_len(owners.remove(i));
888 assert forall|j: int|
889 0 <= j < Self::view_helper(owners.remove(i)).len() implies Self::view_helper(
890 owners.remove(i),
891 )[j] == Self::view_helper(owners).remove(i)[j] by {
892 Self::view_helper_index(owners.remove(i), j);
893 if j < i {
894 Self::view_helper_index(owners, j);
895 } else {
896 Self::view_helper_index(owners, j + 1);
897 }
898 };
899 }
900
901 pub proof fn view_helper_insert(owners: Seq<LinkOwner>, i: int, v: LinkOwner)
904 requires
905 0 <= i <= owners.len(),
906 ensures
907 Self::view_helper(owners.insert(i, v)) == Self::view_helper(owners).insert(i, v.view()),
908 {
909 Self::view_preserves_len(owners);
910 Self::view_preserves_len(owners.insert(i, v));
911 assert forall|j: int|
912 0 <= j < Self::view_helper(
913 owners.insert(i, v),
914 ).len() implies #[trigger] Self::view_helper(owners.insert(i, v))[j]
915 == Self::view_helper(owners).insert(i, v.view())[j] by {
916 Self::view_helper_index(owners.insert(i, v), j);
917 if j < i {
918 Self::view_helper_index(owners, j);
919 } else if j == i {
920 } else {
922 Self::view_helper_index(owners, j - 1);
923 }
924 };
925 }
926}
927
928impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> View for LinkedListOwner<M> {
929 type V = LinkedListModel;
930
931 open spec fn view(&self) -> Self::V {
932 LinkedListModel { list: Self::view_helper(self.list) }
933 }
934}
935
936impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> InvView for LinkedListOwner<M> {
937 proof fn view_preserves_inv(self) {
938 }
939}
940
941impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedListOwner<M> {
942 #[verifier::external_body]
948 pub proof fn tracked_take(tracked owner: &mut Self) -> (tracked res: Self)
949 ensures
950 res == *old(owner),
951 final(owner).list == Seq::<LinkOwner>::empty(),
952 final(owner).inv(),
953 {
954 unimplemented!()
955 }
956
957 #[verifier::external_body]
961 pub proof fn tracked_destroy_empty(tracked self)
962 requires
963 self.list =~= Seq::<LinkOwner>::empty(),
964 {
965 unimplemented!()
966 }
967}
968
969impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for LinkedList<M> {
970 type Owner = LinkedListOwner<M>;
971
972 open spec fn wf(self, owner: Self::Owner) -> bool {
977 &&& self.front is None <==> owner.list.len() == 0
978 &&& self.back is None <==> owner.list.len() == 0
979 &&& owner.list.len() > 0 ==> self.front is Some && self.front->0.addr()
980 == owner.list[0].paddr && self.back is Some && self.back->0.addr()
981 == owner.list[owner.list.len() - 1].paddr
982 &&& self.size == owner.list.len()
983 &&& self.list_id == owner.list_id
984 }
985}
986
987pub ghost struct CursorModel {
988 pub ghost fore: Seq<LinkModel>,
989 pub ghost rear: Seq<LinkModel>,
990 pub ghost list_model: LinkedListModel,
991}
992
993impl Inv for CursorModel {
994 open spec fn inv(self) -> bool {
995 self.list_model.inv()
996 }
997}
998
999pub tracked struct CursorOwner<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
1000 pub list_own: LinkedListOwner<M>,
1001 pub ghost index: int,
1002}
1003
1004impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Inv for CursorOwner<M> {
1005 open spec fn inv(self) -> bool {
1006 &&& 0 <= self.index <= self.length()
1007 &&& self.list_own.inv()
1008 }
1009}
1010
1011impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> View for CursorOwner<M> {
1012 type V = CursorModel;
1013
1014 open spec fn view(&self) -> Self::V {
1015 let list = self.list_own.view();
1016 CursorModel {
1017 fore: list.list.take(self.index),
1018 rear: list.list.skip(self.index),
1019 list_model: list,
1020 }
1021 }
1022}
1023
1024impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> InvView for CursorOwner<M> {
1025 proof fn view_preserves_inv(self) {
1026 }
1027}
1028
1029impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> OwnerOf for CursorMut<'a, M> {
1030 type Owner = CursorOwner<M>;
1031
1032 open spec fn wf(self, owner: Self::Owner) -> bool {
1036 &&& 0 <= owner.index < owner.length() ==> self.current.is_some() && self.current->0.addr()
1037 == owner.list_own.list[owner.index].paddr
1038 &&& owner.index == owner.list_own.list.len() ==> self.current.is_none()
1039 &&& (*self.list).wf(owner.list_own)
1040 }
1041}
1042
1043impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
1044 pub open spec fn wf_region(self, owner: LinkedListOwner<M>, regions: MetaRegionOwners) -> bool {
1049 &&& self.front is None <==> owner.list.len() == 0
1050 &&& self.back is None <==> owner.list.len() == 0
1051 &&& owner.list.len() > 0 ==> self.front is Some && self.front->0.addr()
1052 == owner.list[0].paddr && owner.meta_perm_of(regions, 0).pptr().addr()
1053 == self.front->0.addr() && self.front->0.ptr == owner.meta_perm_of(
1054 regions,
1055 0,
1056 ).points_to.pptr() && self.back is Some && self.back->0.addr()
1057 == owner.list[owner.list.len() - 1].paddr && owner.meta_perm_of(
1058 regions,
1059 owner.list.len() - 1,
1060 ).pptr().addr() == self.back->0.addr() && self.back->0.ptr == owner.meta_perm_of(
1061 regions,
1062 owner.list.len() - 1,
1063 ).points_to.pptr()
1064 &&& self.size == owner.list.len()
1065 &&& self.list_id == owner.list_id
1066 }
1067}
1068
1069impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M> {
1070 pub open spec fn wf_region(self, owner: CursorOwner<M>, regions: MetaRegionOwners) -> bool {
1073 &&& 0 <= owner.index < owner.length() ==> self.current.is_some() && self.current->0.addr()
1074 == owner.list_own.list[owner.index].paddr && owner.list_own.meta_perm_of(
1075 regions,
1076 owner.index,
1077 ).pptr().addr() == self.current->0.addr() && self.current->0.ptr
1078 == owner.list_own.meta_perm_of(regions, owner.index).points_to.pptr()
1079 &&& owner.index == owner.list_own.list.len() ==> self.current.is_none()
1080 &&& (*self.list).wf_region(owner.list_own, regions)
1081 }
1082}
1083
1084impl CursorModel {
1085 pub open spec fn current(self) -> Option<LinkModel> {
1086 if self.rear.len() > 0 {
1087 Some(self.rear[0])
1088 } else {
1089 None
1090 }
1091 }
1092}
1093
1094impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorOwner<M> {
1095 pub open spec fn length(self) -> int {
1096 self.list_own.list.len() as int
1097 }
1098
1099 pub open spec fn wf_with_region(self, regions: MetaRegionOwners) -> bool {
1103 &&& 0 <= self.index <= self.length()
1104 &&& self.list_own.relate_region(regions)
1105 }
1106
1107 pub open spec fn current(self) -> Option<LinkOwner> {
1108 if 0 <= self.index < self.length() {
1109 Some(self.list_own.list[self.index])
1110 } else {
1111 None
1112 }
1113 }
1114
1115 pub open spec fn list_insert(cursor: Self, link: LinkOwner, list_id: u64) -> (Self, LinkOwner)
1116 recommends
1117 list_id != 0,
1118 0 <= cursor.index <= cursor.list_own.list.len(),
1119 cursor.list_own.list.len() > 0 ==> list_id == cursor.list_own.list_id,
1120 {
1121 let link = LinkOwner { paddr: link.paddr, in_list: list_id };
1122 (
1123 Self {
1124 list_own: LinkedListOwner::<M> {
1125 list: cursor.list_own.list.insert(cursor.index, link),
1126 list_id,
1127 _marker: PhantomData,
1128 },
1129 index: cursor.index + 1,
1130 },
1131 link,
1132 )
1133 }
1134
1135 pub proof fn tracked_list_insert(
1144 tracked cursor: &mut Self,
1145 tracked link: &mut LinkOwner,
1146 list_id: u64,
1147 )
1148 requires
1149 list_id != 0,
1150 0 <= old(cursor).index <= old(cursor).list_own.list.len(),
1151 old(cursor).list_own.list.len() > 0 ==> list_id == old(cursor).list_own.list_id,
1152 old(cursor).list_own.list_id != 0 ==> list_id == old(cursor).list_own.list_id,
1153 ensures
1154 ({
1155 let res = Self::list_insert(*old(cursor), *old(link), list_id);
1156
1157 res.0 == *final(cursor) && res.1 == *final(link)
1158 }),
1159 {
1160 let ghost idx = cursor.index;
1161 let ghost link_paddr = link.paddr;
1162 let tracked list_entry = LinkOwner { paddr: link_paddr, in_list: list_id };
1163
1164 cursor.list_own.list.tracked_insert(idx, list_entry);
1165 cursor.list_own.list_id = list_id;
1166 cursor.index = idx + 1;
1167 *link = LinkOwner { paddr: link_paddr, in_list: list_id };
1168 }
1169
1170 pub open spec fn front_owner(list_own: LinkedListOwner<M>) -> Self {
1171 CursorOwner::<M> { list_own: list_own, index: 0 }
1172 }
1173
1174 pub open spec fn cursor_mut_at_owner(list_own: LinkedListOwner<M>, index: int) -> Self {
1175 CursorOwner::<M> { list_own: list_own, index: index }
1176 }
1177
1178 pub proof fn tracked_cursor_mut_at_owner(
1179 tracked list_own: LinkedListOwner<M>,
1180 index: int,
1181 ) -> tracked Self
1182 returns
1183 Self::cursor_mut_at_owner(list_own, index),
1184 {
1185 let tracked res = CursorOwner::<M> { list_own, index };
1186 res
1187 }
1188
1189 pub proof fn tracked_front_owner(tracked list_own: LinkedListOwner<M>) -> tracked Self
1190 returns
1191 Self::front_owner(list_own),
1192 {
1193 let tracked res = CursorOwner::<M> { list_own, index: 0 };
1194 res
1195 }
1196
1197 pub open spec fn back_owner(list_own: LinkedListOwner<M>) -> Self {
1198 CursorOwner::<M> {
1199 list_own: list_own,
1200 index: if list_own.list.len() > 0 {
1201 list_own.list.len() - 1
1202 } else {
1203 0
1204 },
1205 }
1206 }
1207
1208 #[verifier::external_body]
1209 pub proof fn tracked_back_owner(list_own: LinkedListOwner<M>) -> (tracked res: Self)
1210 ensures
1211 res == Self::back_owner(list_own),
1212 {
1213 CursorOwner::<M> {
1214 list_own: list_own,
1215 index: if list_own.list.len() > 0 {
1216 list_own.list.len() - 1
1217 } else {
1218 0
1219 },
1220 }
1221 }
1222
1223 pub open spec fn ghost_owner(list_own: LinkedListOwner<M>) -> Self {
1224 CursorOwner::<M> { list_own: list_own, index: list_own.list.len() as int }
1225 }
1226
1227 #[verifier::external_body]
1228 pub proof fn tracked_ghost_owner(list_own: LinkedListOwner<M>) -> (tracked res: Self)
1229 ensures
1230 res == Self::ghost_owner(list_own),
1231 {
1232 CursorOwner::<M> { list_own: list_own, index: list_own.list.len() as int }
1233 }
1234}
1235
1236impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> UniqueFrameOwner<Link<M>> {
1237 pub open spec fn frame_link_inv(&self, regions: MetaRegionOwners) -> bool {
1238 &&& self.meta_perm_of(regions).value().metadata.prev is None
1239 &&& self.meta_perm_of(regions).value().metadata.next is None
1240 &&& self.meta_own.paddr == self.meta_perm_of(regions).addr()
1241 }
1242}
1243
1244pub struct MetadataAsLink<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
1245 pub metadata: M,
1246 pub next: Option<PPtr<MetaSlot>>,
1247 pub prev: Option<PPtr<MetaSlot>>,
1248 pub ref_count: u64,
1249 pub vtable_ptr: MemContents<usize>,
1250 pub in_list: u64,
1251}
1252
1253impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Repr<MetaSlot> for MetadataAsLink<M> {
1254 type Perm = MetadataInnerPerms;
1255
1256 open spec fn wf(r: MetaSlot, perm: MetadataInnerPerms) -> bool {
1257 &&& <Metadata<Link<M>> as Repr<MetaSlot>>::wf(r, perm)
1258 }
1259
1260 open spec fn to_repr_spec(self, perm: MetadataInnerPerms) -> (MetaSlot, MetadataInnerPerms) {
1261 <Metadata<Link<M>> as Repr<MetaSlot>>::to_repr_spec(
1262 <Metadata<Link<M>> as FromSpec<MetadataAsLink<M>>>::from_spec(self),
1263 perm,
1264 )
1265 }
1266
1267 #[verifier::external_body]
1268 fn to_repr(self, Tracked(perm): Tracked<&mut MetadataInnerPerms>) -> MetaSlot {
1269 unimplemented!()
1270 }
1271
1272 open spec fn from_repr_spec(r: MetaSlot, perm: MetadataInnerPerms) -> Self {
1273 <MetadataAsLink<M> as FromSpec<Metadata<Link<M>>>>::from_spec(
1274 <Metadata<Link<M>> as Repr<MetaSlot>>::from_repr_spec(r, perm),
1275 )
1276 }
1277
1278 #[verifier::external_body]
1279 fn from_repr(r: MetaSlot, Tracked(perm): Tracked<&MetadataInnerPerms>) -> Self {
1280 unimplemented!()
1281 }
1282
1283 #[verifier::external_body]
1284 fn from_borrowed<'a>(
1285 r: &'a MetaSlot,
1286 Tracked(perm): Tracked<&'a MetadataInnerPerms>,
1287 ) -> &'a Self {
1288 unimplemented!()
1289 }
1290
1291 proof fn from_to_repr(self, perm: MetadataInnerPerms) {
1292 let md = <Metadata<Link<M>> as FromSpec<MetadataAsLink<M>>>::from_spec(self);
1293 <Metadata<Link<M>> as Repr<MetaSlot>>::from_to_repr(md, perm);
1294 }
1295
1296 proof fn to_from_repr(r: MetaSlot, perm: MetadataInnerPerms) {
1297 let md = <Metadata<Link<M>> as Repr<MetaSlot>>::from_repr_spec(r, perm);
1298 <Metadata<Link<M>> as Repr<MetaSlot>>::to_from_repr(r, perm);
1299
1300 }
1301
1302 proof fn to_repr_wf(self, perm: MetadataInnerPerms) {
1303 let md = <Metadata<Link<M>> as FromSpec<MetadataAsLink<M>>>::from_spec(self);
1304 <Metadata<Link<M>> as Repr<MetaSlot>>::to_repr_wf(md, perm);
1305 <Metadata<Link<M>> as Repr<MetaSlot>>::from_to_repr(md, perm);
1306 }
1307}
1308
1309impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> FromSpecImpl<Metadata<Link<M>>> for MetadataAsLink<M> {
1310 open spec fn obeys_from_spec() -> bool {
1311 true
1312 }
1313
1314 open spec fn from_spec(m: Metadata<Link<M>>) -> MetadataAsLink<M> {
1315 MetadataAsLink {
1316 metadata: m.metadata.meta,
1317 next: match m.metadata.next {
1318 Some(repr_ptr) => Some(repr_ptr.ptr),
1319 None => None,
1320 },
1321 prev: match m.metadata.prev {
1322 Some(repr_ptr) => Some(repr_ptr.ptr),
1323 None => None,
1324 },
1325 ref_count: m.ref_count,
1326 vtable_ptr: m.vtable_ptr,
1327 in_list: m.in_list,
1328 }
1329 }
1330}
1331
1332impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> From<Metadata<Link<M>>> for MetadataAsLink<M> {
1333 fn from(m: Metadata<Link<M>>) -> Self {
1334 let next = match m.metadata.next {
1335 Some(repr_ptr) => Some(repr_ptr.ptr),
1336 None => None,
1337 };
1338 let prev = match m.metadata.prev {
1339 Some(repr_ptr) => Some(repr_ptr.ptr),
1340 None => None,
1341 };
1342 MetadataAsLink {
1343 metadata: m.metadata.meta,
1344 next,
1345 prev,
1346 ref_count: m.ref_count,
1347 vtable_ptr: m.vtable_ptr,
1348 in_list: m.in_list,
1349 }
1350 }
1351}
1352
1353impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> FromSpecImpl<MetadataAsLink<M>> for Metadata<Link<M>> {
1354 open spec fn obeys_from_spec() -> bool {
1355 true
1356 }
1357
1358 open spec fn from_spec(m: MetadataAsLink<M>) -> Metadata<Link<M>> {
1359 Metadata {
1360 metadata: Link {
1361 next: match m.next {
1362 Some(pptr) => Some(ReprPtr { ptr: pptr, _T: PhantomData }),
1363 None => None,
1364 },
1365 prev: match m.prev {
1366 Some(pptr) => Some(ReprPtr { ptr: pptr, _T: PhantomData }),
1367 None => None,
1368 },
1369 meta: m.metadata,
1370 },
1371 ref_count: m.ref_count,
1372 vtable_ptr: m.vtable_ptr,
1373 in_list: m.in_list,
1374 }
1375 }
1376}
1377
1378impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> From<MetadataAsLink<M>> for Metadata<Link<M>> {
1379 fn from(m: MetadataAsLink<M>) -> Self {
1380 let next = match m.next {
1381 Some(pptr) => Some(ReprPtr { ptr: pptr, _T: PhantomData }),
1382 None => None,
1383 };
1384 let prev = match m.prev {
1385 Some(pptr) => Some(ReprPtr { ptr: pptr, _T: PhantomData }),
1386 None => None,
1387 };
1388 Metadata {
1389 metadata: Link { next, prev, meta: m.metadata },
1390 ref_count: m.ref_count,
1391 vtable_ptr: m.vtable_ptr,
1392 in_list: m.in_list,
1393 }
1394 }
1395}
1396
1397impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> MetadataAsLink<M> {
1398 pub fn cast_to_metadata(ptr: ReprPtr<MetaSlot, Self>) -> (res: ReprPtr<
1399 MetaSlot,
1400 Metadata<Link<M>>,
1401 >)
1402 ensures
1403 res.addr() == ptr.addr(),
1404 res.ptr == ptr.ptr,
1405 {
1406 ReprPtr { ptr: ptr.ptr, _T: PhantomData }
1407 }
1408
1409 pub fn cast_from_metadata(ptr: ReprPtr<MetaSlot, Metadata<Link<M>>>) -> (res: ReprPtr<
1410 MetaSlot,
1411 Self,
1412 >)
1413 ensures
1414 res.addr() == ptr.addr(),
1415 res.ptr == ptr.ptr,
1416 {
1417 ReprPtr { ptr: ptr.ptr, _T: PhantomData }
1418 }
1419}
1420
1421}