1use vstd::prelude::*;
58use vstd_extra::{cast_ptr::Repr, ownership::*, set_extra::lemma_finite_int_set_has_unused};
59
60use crate::specs::{
61 arch::valid_frame_paddr,
62 mm::frame::{
63 linked_list::linked_list_owners::{CursorOwner, LinkOwner, LinkedListOwner, MetaSlotSmall},
64 mapping::frame_to_index,
65 meta_owners::PageUsage,
66 meta_region_owners::MetaRegionOwners,
67 unique::UniqueFrameOwner,
68 },
69};
70
71use crate::mm::{
72 Paddr,
73 frame::{
74 AnyFrameMeta, Link,
75 meta::{REF_COUNT_UNIQUE, REF_COUNT_UNUSED},
76 },
77};
78
79verus! {
80
81pub type ListId = int;
83
84pub type LooseId = int;
87
88pub type CursorId = ListId;
93
94pub open spec fn list_registry_ok<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
106 regions: MetaRegionOwners,
107 lo: LinkedListOwner<M>,
108) -> bool {
109 &&& forall|i: int|
110 #![trigger lo.slot_index_at(i)]
111 0 <= i < lo.list.len() ==> regions.slot_owners[lo.slot_index_at(
112 i,
113 )].inner_perms.in_list.value() == lo.list_id
114 &&& lo.list_id != 0 ==> forall|idx: int|
115 #![trigger regions.slot_owners[idx]]
116 regions.slot_owners.contains_key(idx)
117 && regions.slot_owners[idx].inner_perms.in_list.value() == lo.list_id ==> exists|i: int|
118
119 0 <= i < lo.list.len() && lo.slot_index_at(i) == idx
120}
121
122pub tracked struct ListStore<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
131 pub regions: MetaRegionOwners,
132 pub lists: Map<ListId, LinkedListOwner<M>>,
133 pub loose: Map<LooseId, UniqueFrameOwner<Link<M>>>,
134 pub cursors: Map<CursorId, CursorOwner<M>>,
135}
136
137impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M> {
138 pub open spec fn inv(self) -> bool {
140 &&& self.regions.inv()
141 &&& forall|id: ListId| #[trigger]
144 self.lists.dom().contains(id) ==> {
145 &&& self.lists[id].inv()
146 &&& self.lists[id].relate_region(self.regions)
147 }
148 &&& forall|lid: LooseId| #[trigger]
155 self.loose.dom().contains(lid) ==> {
156 &&& self.loose[lid].inv()
157 &&& self.loose[lid].global_inv(self.regions)
158 &&& self.loose[lid].frame_link_inv(self.regions)
159 &&& self.regions.slot_owners[self.loose[lid].slot_index].inner_perms.in_list.value()
160 == 0
161 }
162 &&& forall|id1: ListId, id2: ListId|
169 #![trigger self.lists.dom().contains(id1), self.lists.dom().contains(id2)]
170 self.lists.dom().contains(id1) && self.lists.dom().contains(id2)
171 && self.lists[id1].list_id == self.lists[id2].list_id && self.lists[id1].list_id
172 != 0 ==> id1
173 == id2
174 &&& forall|lid1: LooseId, lid2: LooseId|
177 #![trigger self.loose.dom().contains(lid1), self.loose.dom().contains(lid2)]
178 self.loose.dom().contains(lid1) && self.loose.dom().contains(lid2)
179 && self.loose[lid1].slot_index == self.loose[lid2].slot_index ==> lid1
180 == lid2
181 &&& self.lists.dom().disjoint(
185 self.cursors.dom(),
186 )
187 &&& forall|cid: CursorId| #[trigger]
194 self.cursors.dom().contains(cid) ==> {
195 &&& self.cursors[cid].list_own.inv()
196 &&& self.cursors[cid].wf_with_region(self.regions)
197 }
198 &&& forall|id: ListId, cid: CursorId|
201 #![trigger self.lists.dom().contains(id), self.cursors.dom().contains(cid)]
202 self.lists.dom().contains(id) && self.cursors.dom().contains(cid)
203 && self.lists[id].list_id == self.cursors[cid].list_own.list_id
204 && self.lists[id].list_id != 0
205 ==> false
206 &&& forall|cid1: CursorId, cid2: CursorId|
208 #![trigger self.cursors.dom().contains(cid1), self.cursors.dom().contains(cid2)]
209 self.cursors.dom().contains(cid1) && self.cursors.dom().contains(cid2)
210 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
211 && self.cursors[cid1].list_own.list_id != 0 ==> cid1
212 == cid2
213 &&& forall|id: ListId| #[trigger]
217 self.lists.dom().contains(id) ==> list_registry_ok(
218 self.regions,
219 self.lists[id],
220 )
221 &&& forall|cid: CursorId| #[trigger]
223 self.cursors.dom().contains(cid) ==> list_registry_ok(
224 self.regions,
225 self.cursors[cid].list_own,
226 )
227 }
228}
229
230pub proof fn tracked_empty_list_owner<M: AnyFrameMeta + Repr<MetaSlotSmall>>() -> (tracked res:
238 LinkedListOwner<M>)
239 ensures
240 res.list =~= Seq::<LinkOwner>::empty(),
241 res.list_id == 0,
242{
243 let tracked list = Seq::<LinkOwner>::tracked_empty();
244 let tracked res = LinkedListOwner::<M> { list, list_id: 0, _marker: core::marker::PhantomData };
245 res
246}
247
248pub open spec fn fresh_list_id<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
252 lists: Map<ListId, LinkedListOwner<M>>,
253 cursors: Map<CursorId, CursorOwner<M>>,
254) -> ListId {
255 choose|id: ListId| !lists.dom().contains(id) && !cursors.dom().contains(id)
256}
257
258pub proof fn lemma_fresh_list_id_not_in_dom<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
259 lists: Map<ListId, LinkedListOwner<M>>,
260 cursors: Map<CursorId, CursorOwner<M>>,
261)
262 ensures
263 !lists.dom().contains(fresh_list_id(lists, cursors)) && !cursors.dom().contains(
264 fresh_list_id(lists, cursors),
265 ),
266{
267 lemma_finite_int_set_has_unused(lists.dom() + cursors.dom());
268}
269
270pub proof fn push_front_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
288 tracked regions: &mut MetaRegionOwners,
289 tracked owner: &mut LinkedListOwner<M>,
290 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
291 used_ids: Set<u64>,
292)
293 requires
294 old(regions).inv(),
295 old(owner).inv(),
296 old(owner).relate_region(*old(regions)),
297 old(frame_own).inv(),
298 old(frame_own).global_inv(*old(regions)),
299 old(frame_own).frame_link_inv(*old(regions)),
300 old(regions).slot_owners[old(frame_own).slot_index].inner_perms.in_list.value() == 0,
301 ensures
302 final(regions).inv(),
303 final(owner).inv(),
304 final(owner).relate_region(*final(regions)),
305 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
306 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
307 final(owner).list_id != 0,
308 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
309 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
310 final(frame_own).meta_own.in_list == final(owner).list_id,
311 final(regions).frame_obligations =~= old(regions).frame_obligations.remove(
312 old(frame_own).slot_index,
313 ),
314 forall|k: int|
315 #![trigger final(regions).slots[k]]
316 #![trigger final(regions).slot_owners[k]]
317 k != old(frame_own).slot_index && (old(owner).list.len() > 0 ==> k != old(
318 owner,
319 ).slot_index_at(0)) ==> final(regions).slots[k] == old(regions).slots[k]
320 && final(regions).slot_owners[k] == old(regions).slot_owners[k],
321 forall|l: LinkedListOwner<M>|
322 #![trigger l.relate_region(*old(regions))]
323 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
324 ==> l.relate_region(*final(regions)),
325 list_registry_ok(*final(regions), *final(owner)),
329 forall|l: LinkedListOwner<M>|
334 #![trigger l.relate_region(*old(regions))]
335 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
336 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
337 forall|fo: UniqueFrameOwner<Link<M>>|
343 #![trigger fo.global_inv(*old(regions))]
344 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
345 regions,
346 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 && fo.slot_index != old(
347 frame_own,
348 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
349 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
350{
351 insert_before_at_embedded(regions, owner, frame_own, 0, used_ids);
352}
353
354pub open spec fn fresh_loose_id<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
356 m: Map<LooseId, UniqueFrameOwner<Link<M>>>,
357) -> LooseId {
358 choose|id: LooseId| !m.dom().contains(id)
359}
360
361pub proof fn lemma_fresh_loose_id_not_in_dom<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
362 m: Map<LooseId, UniqueFrameOwner<Link<M>>>,
363)
364 ensures
365 !m.dom().contains(fresh_loose_id(m)),
366{
367 lemma_finite_int_set_has_unused(m.dom());
368}
369
370pub proof fn tracked_pop_front_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
386 tracked regions: &mut MetaRegionOwners,
387 tracked owner: &mut LinkedListOwner<M>,
388) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
389 requires
390 old(regions).inv(),
391 old(owner).inv(),
392 old(owner).relate_region(*old(regions)),
393 old(owner).list.len() > 0,
394 ensures
395 final(regions).inv(),
396 final(owner).inv(),
397 final(owner).relate_region(*final(regions)),
398 final(owner).list == old(owner).list.remove(0),
399 final(owner).list_id == old(owner).list_id,
400 frame_own.inv(),
402 frame_own.global_inv(*final(regions)),
403 frame_own.frame_link_inv(*final(regions)),
404 frame_own.slot_index == old(owner).slot_index_at(0),
405 final(regions).slot_owners[frame_own.slot_index].inner_perms.in_list.value() == 0,
406 final(regions).frame_obligations =~= old(regions).frame_obligations.insert(
408 old(owner).slot_index_at(0),
409 ),
410 forall|j: int|
413 #![trigger final(regions).slots[j]]
414 #![trigger final(regions).slot_owners[j]]
415 j != old(owner).slot_index_at(0) && (old(owner).list.len() > 1 ==> j != old(
416 owner,
417 ).slot_index_at(1)) ==> final(regions).slots[j] == old(regions).slots[j]
418 && final(regions).slot_owners[j] == old(regions).slot_owners[j],
419 forall|l: LinkedListOwner<M>|
421 #![trigger l.relate_region(*old(regions))]
422 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
423 ==> l.relate_region(*final(regions)),
424 list_registry_ok(*final(regions), *final(owner)),
428 forall|l: LinkedListOwner<M>|
433 #![trigger l.relate_region(*old(regions))]
434 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
435 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
436 forall|fo: UniqueFrameOwner<Link<M>>|
439 #![trigger fo.global_inv(*old(regions))]
440 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
441 regions,
442 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
443 *final(regions),
444 ) && fo.frame_link_inv(*final(regions))
445 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0
446 && fo.slot_index != old(owner).slot_index_at(0),
447{
448 let tracked frame_own = take_at_embedded(regions, owner, 0);
449 frame_own
450}
451
452pub proof fn lemma_push_back_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
457 tracked regions: &mut MetaRegionOwners,
458 tracked owner: &mut LinkedListOwner<M>,
459 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
460 used_ids: Set<u64>,
461)
462 requires
463 old(regions).inv(),
464 old(owner).inv(),
465 old(owner).relate_region(*old(regions)),
466 old(frame_own).inv(),
467 old(frame_own).global_inv(*old(regions)),
468 old(frame_own).frame_link_inv(*old(regions)),
469 old(regions).slot_owners[old(frame_own).slot_index].inner_perms.in_list.value() == 0,
470 ensures
471 final(regions).inv(),
472 final(owner).inv(),
473 final(owner).relate_region(*final(regions)),
474 old(owner).list.len() > 0 ==> final(owner).list == old(owner).list.insert(
475 old(owner).list.len() - 1,
476 final(frame_own).meta_own,
477 ),
478 old(owner).list.len() == 0 ==> final(owner).list == old(owner).list.insert(
479 0,
480 final(frame_own).meta_own,
481 ),
482 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
483 final(owner).list_id != 0,
484 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
485 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
486 final(frame_own).meta_own.in_list == final(owner).list_id,
487 final(regions).frame_obligations =~= old(regions).frame_obligations.remove(
488 old(frame_own).slot_index,
489 ),
490 forall|k: int|
491 #![trigger final(regions).slots[k]]
492 #![trigger final(regions).slot_owners[k]]
493 k != old(frame_own).slot_index && (old(owner).list.len() > 1 ==> k != old(
494 owner,
495 ).slot_index_at(old(owner).list.len() - 2)) && (old(owner).list.len() > 0 ==> k != old(
496 owner,
497 ).slot_index_at(old(owner).list.len() - 1)) ==> final(regions).slots[k] == old(
498 regions,
499 ).slots[k] && final(regions).slot_owners[k] == old(regions).slot_owners[k],
500 forall|l: LinkedListOwner<M>|
501 #![trigger l.relate_region(*old(regions))]
502 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
503 ==> l.relate_region(*final(regions)),
504 list_registry_ok(*final(regions), *final(owner)),
508 forall|l: LinkedListOwner<M>|
513 #![trigger l.relate_region(*old(regions))]
514 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
515 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
516 forall|fo: UniqueFrameOwner<Link<M>>|
517 #![trigger fo.global_inv(*old(regions))]
518 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
519 regions,
520 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 && fo.slot_index != old(
521 frame_own,
522 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
523 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
524{
525 let ghost n = if owner.list.len() > 0 {
526 owner.list.len() - 1
527 } else {
528 0
529 };
530 insert_before_at_embedded(regions, owner, frame_own, n, used_ids);
531}
532
533pub proof fn tracked_pop_back_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
538 tracked regions: &mut MetaRegionOwners,
539 tracked owner: &mut LinkedListOwner<M>,
540) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
541 requires
542 old(regions).inv(),
543 old(owner).inv(),
544 old(owner).relate_region(*old(regions)),
545 old(owner).list.len() > 0,
546 ensures
547 final(regions).inv(),
548 final(owner).inv(),
549 final(owner).relate_region(*final(regions)),
550 final(owner).list == old(owner).list.remove(old(owner).list.len() - 1),
551 final(owner).list_id == old(owner).list_id,
552 frame_own.inv(),
553 frame_own.global_inv(*final(regions)),
554 frame_own.frame_link_inv(*final(regions)),
555 frame_own.slot_index == old(owner).slot_index_at(old(owner).list.len() - 1),
556 final(regions).slot_owners[frame_own.slot_index].inner_perms.in_list.value() == 0,
557 final(regions).frame_obligations =~= old(regions).frame_obligations.insert(
558 old(owner).slot_index_at(old(owner).list.len() - 1),
559 ),
560 forall|j: int|
561 #![trigger final(regions).slots[j]]
562 #![trigger final(regions).slot_owners[j]]
563 j != old(owner).slot_index_at(old(owner).list.len() - 1) && (old(owner).list.len() > 1
564 ==> j != old(owner).slot_index_at(old(owner).list.len() - 2))
565 ==> final(regions).slots[j] == old(regions).slots[j]
566 && final(regions).slot_owners[j] == old(regions).slot_owners[j],
567 forall|l: LinkedListOwner<M>|
568 #![trigger l.relate_region(*old(regions))]
569 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
570 ==> l.relate_region(*final(regions)),
571 list_registry_ok(*final(regions), *final(owner)),
575 forall|l: LinkedListOwner<M>|
580 #![trigger l.relate_region(*old(regions))]
581 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
582 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
583 forall|fo: UniqueFrameOwner<Link<M>>|
584 #![trigger fo.global_inv(*old(regions))]
585 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
586 regions,
587 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
588 *final(regions),
589 ) && fo.frame_link_inv(*final(regions))
590 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0
591 && fo.slot_index != old(owner).slot_index_at(old(owner).list.len() - 1),
592{
593 let ghost n = owner.list.len() - 1;
594 let tracked frame_own = take_at_embedded(regions, owner, n);
595 frame_own
596}
597
598pub axiom fn insert_before_at_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
604 tracked regions: &mut MetaRegionOwners,
605 tracked owner: &mut LinkedListOwner<M>,
606 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
607 n: int,
608 used_ids: Set<u64>,
609)
610 requires
611 old(regions).inv(),
612 old(owner).inv(),
613 old(owner).relate_region(*old(regions)),
614 old(frame_own).inv(),
615 old(frame_own).global_inv(*old(regions)),
616 old(frame_own).frame_link_inv(*old(regions)),
617 old(regions).slot_owners[old(frame_own).slot_index].inner_perms.in_list.value() == 0,
618 0 <= n <= old(owner).list.len(),
619 ensures
620 final(regions).inv(),
621 final(owner).inv(),
622 final(owner).relate_region(*final(regions)),
623 final(owner).list == old(owner).list.insert(n, final(frame_own).meta_own),
624 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
625 final(owner).list_id != 0,
626 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
627 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
628 final(frame_own).meta_own.in_list == final(owner).list_id,
629 final(regions).frame_obligations =~= old(regions).frame_obligations.remove(
630 old(frame_own).slot_index,
631 ),
632 forall|k: int|
633 #![trigger final(regions).slots[k]]
634 #![trigger final(regions).slot_owners[k]]
635 k != old(frame_own).slot_index && (n > 0 ==> k != old(owner).slot_index_at(n - 1)) && (n
636 < old(owner).list.len() ==> k != old(owner).slot_index_at(n))
637 ==> final(regions).slots[k] == old(regions).slots[k]
638 && final(regions).slot_owners[k] == old(regions).slot_owners[k],
639 forall|l: LinkedListOwner<M>|
640 #![trigger l.relate_region(*old(regions))]
641 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
642 ==> l.relate_region(*final(regions)),
643 list_registry_ok(*final(regions), *final(owner)),
647 forall|l: LinkedListOwner<M>|
652 #![trigger l.relate_region(*old(regions))]
653 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
654 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
655 forall|fo: UniqueFrameOwner<Link<M>>|
656 #![trigger fo.global_inv(*old(regions))]
657 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
658 regions,
659 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 && fo.slot_index != old(
660 frame_own,
661 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
662 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
663;
664
665pub axiom fn take_at_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
671 tracked regions: &mut MetaRegionOwners,
672 tracked owner: &mut LinkedListOwner<M>,
673 n: int,
674) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
675 requires
676 old(regions).inv(),
677 old(owner).inv(),
678 old(owner).relate_region(*old(regions)),
679 0 <= n < old(owner).list.len(),
680 ensures
681 final(regions).inv(),
682 final(owner).inv(),
683 final(owner).relate_region(*final(regions)),
684 final(owner).list == old(owner).list.remove(n),
685 final(owner).list_id == old(owner).list_id,
686 frame_own.inv(),
687 frame_own.global_inv(*final(regions)),
688 frame_own.frame_link_inv(*final(regions)),
689 frame_own.slot_index == old(owner).slot_index_at(n),
690 final(regions).slot_owners[frame_own.slot_index].inner_perms.in_list.value() == 0,
691 final(regions).frame_obligations =~= old(regions).frame_obligations.insert(
692 old(owner).slot_index_at(n),
693 ),
694 forall|j: int|
695 #![trigger final(regions).slots[j]]
696 #![trigger final(regions).slot_owners[j]]
697 j != old(owner).slot_index_at(n) && (n > 0 ==> j != old(owner).slot_index_at(n - 1))
698 && (n < old(owner).list.len() - 1 ==> j != old(owner).slot_index_at(n + 1))
699 ==> final(regions).slots[j] == old(regions).slots[j]
700 && final(regions).slot_owners[j] == old(regions).slot_owners[j],
701 forall|l: LinkedListOwner<M>|
702 #![trigger l.relate_region(*old(regions))]
703 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
704 ==> l.relate_region(*final(regions)),
705 list_registry_ok(*final(regions), *final(owner)),
709 forall|l: LinkedListOwner<M>|
714 #![trigger l.relate_region(*old(regions))]
715 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
716 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
717 forall|fo: UniqueFrameOwner<Link<M>>|
718 #![trigger fo.global_inv(*old(regions))]
719 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
720 regions,
721 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
722 *final(regions),
723 ) && fo.frame_link_inv(*final(regions))
724 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0
725 && fo.slot_index != old(owner).slot_index_at(n),
726;
727
728pub axiom fn list_drop_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
745 tracked regions: &mut MetaRegionOwners,
746 tracked owner: LinkedListOwner<M>,
747)
748 requires
749 old(regions).inv(),
750 owner.inv(),
751 owner.relate_region(*old(regions)),
752 forall|i: int|
753 #![trigger owner.slot_index_at(i)]
754 0 <= i < owner.list.len() ==> old(regions).frame_obligations.count(
755 owner.slot_index_at(i),
756 ) == 0,
757 forall|i: int|
765 #![trigger owner.slot_index_at(i)]
766 0 <= i < owner.list.len() ==> old(regions).slot_owners[owner.slot_index_at(
767 i,
768 )].paths_in_pt.is_empty(),
769 ensures
770 final(regions).inv(),
771 final(regions).slots.dom() =~= old(regions).slots.dom(),
772 owner.list.len() == 0 ==> *final(regions) == *old(regions),
774 forall|i: int|
776 #![trigger owner.slot_index_at(i)]
777 0 <= i < owner.list.len() ==> {
778 let idx = owner.slot_index_at(i);
779 &&& final(regions).slot_owners[idx].inner_perms.ref_count.value()
780 == REF_COUNT_UNUSED
781 &&& final(regions).slot_owners[idx].inner_perms.in_list.value() == 0
782 },
783 forall|idx: int|
785 #![trigger final(regions).slot_owners[idx]]
786 (forall|i: int| 0 <= i < owner.list.len() ==> idx != owner.slot_index_at(i))
787 ==> final(regions).slot_owners[idx] == old(regions).slot_owners[idx]
788 && final(regions).slots[idx] == old(regions).slots[idx]
789 && final(regions).frame_obligations.count(idx) == old(
790 regions,
791 ).frame_obligations.count(idx),
792 forall|l: LinkedListOwner<M>|
794 #![trigger l.relate_region(*old(regions))]
795 l.inv() && l.relate_region(*old(regions)) && l.list_id != owner.list_id
796 ==> l.relate_region(*final(regions)),
797 forall|l: LinkedListOwner<M>|
798 #![trigger l.relate_region(*old(regions))]
799 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
800 && l.list_id != owner.list_id ==> list_registry_ok(*final(regions), l),
801 forall|fo: UniqueFrameOwner<Link<M>>|
804 #![trigger fo.global_inv(*old(regions))]
805 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
806 regions,
807 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
808 *final(regions),
809 ) && fo.frame_link_inv(*final(regions))
810 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
811;
812
813impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M> {
817 pub proof fn step_size(tracked &self, id: ListId) -> (res: nat)
820 requires
821 self.inv(),
822 self.lists.dom().contains(id),
823 ensures
824 res == self.lists[id].list.len(),
825 {
826 self.lists[id].list.len()
827 }
828
829 pub proof fn step_is_empty(tracked &self, id: ListId) -> (res: bool)
831 requires
832 self.inv(),
833 self.lists.dom().contains(id),
834 ensures
835 res <==> self.lists[id].list.len() == 0,
836 {
837 self.lists[id].list.len() == 0
838 }
839
840 pub proof fn step_contains(tracked &self, id: ListId, frame: Paddr) -> (res: bool)
850 requires
851 self.inv(),
852 self.lists.dom().contains(id),
853 ensures
854 res <==> (valid_frame_paddr(frame) && exists|i: int|
855 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i)
856 == frame_to_index(frame)),
857 {
858 let idx = frame_to_index(frame);
859 if valid_frame_paddr(frame) {
860 self.regions.inv_implies_correct_addr(frame);
862 assert(self.regions.slot_owners.contains_key(idx));
863 if self.lists[id].list_id != 0 {
864 assert(list_registry_ok(self.regions, self.lists[id]));
866 let res = self.regions.slot_owners[idx].inner_perms.in_list.value()
867 == self.lists[id].list_id;
868 if res {
869 assert(exists|i: int|
871 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i)
872 == idx);
873 } else {
874 assert forall|i: int|
877 0 <= i < self.lists[id].list.len() implies self.lists[id].slot_index_at(i)
878 != idx by {
879 assert(self.regions.slot_owners[self.lists[id].slot_index_at(
880 i,
881 )].inner_perms.in_list.value() == self.lists[id].list_id);
882 };
883 }
884 res
885 } else {
886 assert(self.lists[id].list.len() == 0);
889 false
890 }
891 } else {
892 false
895 }
896 }
897
898 pub proof fn step_list_new(tracked &mut self) -> (res: ListId)
902 requires
903 old(self).inv(),
904 ensures
905 final(self).inv(),
906 final(self).regions == old(self).regions,
907 final(self).loose == old(self).loose,
908 !old(self).lists.dom().contains(res),
909 final(self).lists == old(self).lists.insert(res, final(self).lists[res]),
910 final(self).lists[res].list.len() == 0,
911 {
912 let ghost old_self = *self;
913 let ghost id = fresh_list_id(self.lists, self.cursors);
914 lemma_fresh_list_id_not_in_dom(self.lists, self.cursors);
915 let tracked empty = tracked_empty_list_owner::<M>();
916 self.lists.tracked_insert(id, empty);
917 assert(self.lists[id].list.len() == 0);
918 assert(self.lists[id].relate_region(self.regions));
923 assert(self.cursors == old_self.cursors);
927 assert(self.lists.dom().disjoint(self.cursors.dom()));
928 assert(self.lists[id].list_id == 0);
929 id
930 }
931
932 pub proof fn step_list_drop(tracked &mut self, id: ListId)
943 requires
944 old(self).inv(),
945 old(self).lists.dom().contains(id),
946 forall|i: int|
947 0 <= i < old(self).lists[id].list.len() ==> old(
948 self,
949 ).regions.frame_obligations.count(#[trigger] old(self).lists[id].slot_index_at(i))
950 == 0,
951 ensures
952 final(self).inv(),
953 !final(self).lists.dom().contains(id),
954 final(self).loose == old(self).loose,
955 final(self).cursors == old(self).cursors,
956 {
957 let ghost old_self = *self;
958 let ghost old_regions = self.regions;
959 let ghost dropped_id = self.lists[id].list_id;
960 let ghost is_empty = self.lists[id].list.len() == 0;
961 assert(self.lists[id].relate_region(self.regions));
962
963 assert forall|i: int|
969 #![trigger self.lists[id].slot_index_at(i)]
970 0 <= i
971 < self.lists[id].list.len() implies self.regions.slot_owners[self.lists[id].slot_index_at(
972 i)].paths_in_pt.is_empty() by {
973 let idx = self.lists[id].slot_index_at(i);
974 let _ = self.lists[id].list[i];
977 self.lists[id].relate_region_at_facts(self.regions, i);
978 assert(self.regions.slot_owners.contains_key(idx));
979 assert(self.regions.slot_owners[idx].inner_perms.ref_count.value() == REF_COUNT_UNIQUE);
980 assert(self.regions.slot_owners[idx].usage is Frame);
981 };
982
983 let tracked owner = self.lists.tracked_remove(id);
984 list_drop_embedded(&mut self.regions, owner);
985 assert(self.lists =~= old_self.lists.remove(id));
986 if is_empty {
987 assert(self.regions == old_regions);
988 }
989 if !is_empty {
994 assert(dropped_id != 0);
995 }
996 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
999 &&& self.lists[i].inv()
1000 &&& self.lists[i].relate_region(self.regions)
1001 } by {
1002 assert(i != id);
1003 assert(old_self.lists.dom().contains(i));
1004 assert(old_self.lists[i] == self.lists[i]);
1005 assert(old_self.lists[i].relate_region(old_regions));
1006 if !is_empty {
1007 assert(self.lists[i].list_id != dropped_id);
1008 }
1009 };
1010
1011 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1013 &&& self.loose[lid2].inv()
1014 &&& self.loose[lid2].global_inv(self.regions)
1015 &&& self.loose[lid2].frame_link_inv(self.regions)
1016 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1017 == 0
1018 } by {
1019 assert(old_self.loose.dom().contains(lid2));
1020 assert(old_self.loose[lid2].global_inv(old_regions));
1021 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1022 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1023 == 0);
1024 };
1025
1026 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1028 &&& self.cursors[cid].list_own.inv()
1029 &&& self.cursors[cid].wf_with_region(self.regions)
1030 } by {
1031 assert(old_self.cursors.dom().contains(cid));
1032 assert(old_self.cursors[cid].wf_with_region(old_regions));
1033 assert(self.cursors[cid].list_own.relate_region(old_regions));
1034 if !is_empty {
1035 assert(self.cursors[cid].list_own.list_id != dropped_id);
1036 }
1037 };
1038
1039 assert forall|i1: ListId, i2: ListId| #[trigger]
1041 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1042 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1043 != 0 implies i1 == i2 by {
1044 assert(old_self.lists.dom().contains(i1));
1045 assert(old_self.lists.dom().contains(i2));
1046 };
1047
1048 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1050 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1051 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1052 assert(old_self.loose.dom().contains(l1));
1053 assert(old_self.loose.dom().contains(l2));
1054 };
1055
1056 assert(self.lists.dom().disjoint(self.cursors.dom()));
1058 assert forall|id2: ListId, cid: CursorId| #[trigger]
1059 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1060 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1061 && self.lists[id2].list_id != 0 implies false by {
1062 assert(old_self.lists.dom().contains(id2));
1063 assert(old_self.cursors.dom().contains(cid));
1064 };
1065 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1066 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1067 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1068 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1069 assert(old_self.cursors.dom().contains(cid1));
1070 assert(old_self.cursors.dom().contains(cid2));
1071 };
1072
1073 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies list_registry_ok(
1075 self.regions,
1076 self.lists[i],
1077 ) by {
1078 assert(old_self.lists.dom().contains(i));
1079 assert(old_self.lists[i] == self.lists[i]);
1080 assert(old_self.lists[i].relate_region(old_regions));
1081 if !is_empty {
1082 assert(self.lists[i].list_id != dropped_id);
1083 }
1084 };
1085 assert forall|cid: CursorId| #[trigger]
1086 self.cursors.dom().contains(cid) implies list_registry_ok(
1087 self.regions,
1088 self.cursors[cid].list_own,
1089 ) by {
1090 assert(old_self.cursors.dom().contains(cid));
1091 assert(old_self.cursors[cid].list_own.relate_region(old_regions));
1092 if !is_empty {
1093 assert(self.cursors[cid].list_own.list_id != dropped_id);
1094 }
1095 };
1096 }
1097
1098 pub proof fn step_push_front(tracked &mut self, id: ListId, lid: LooseId)
1102 requires
1103 old(self).inv(),
1104 old(self).lists.dom().contains(id),
1105 old(self).loose.dom().contains(lid),
1106 ensures
1107 final(self).inv(),
1108 {
1109 let ghost old_self = *self;
1110 let ghost old_regions = self.regions;
1111 let ghost fidx = self.loose[lid].slot_index;
1112 let ghost used = Set::<u64>::full().unwrap().filter(
1114 |x: u64|
1115 (exists|i: ListId| #[trigger]
1116 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
1117 || (exists|cid: CursorId| #[trigger]
1118 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
1119 == x),
1120 );
1121 assert(self.lists[id].relate_region(self.regions));
1123 assert(self.loose[lid].global_inv(self.regions));
1124 assert(self.loose[lid].frame_link_inv(self.regions));
1125 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
1126
1127 let tracked mut owner = self.lists.tracked_remove(id);
1128 let tracked mut frame_own = self.loose.tracked_remove(lid);
1129 push_front_embedded(&mut self.regions, &mut owner, &mut frame_own, used);
1130 self.lists.tracked_insert(id, owner);
1131 assert(self.loose =~= old_self.loose.remove(lid));
1132 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1133 let ghost new_id = self.lists[id].list_id;
1134
1135 assert forall|i: ListId| #[trigger]
1139 self.lists.dom().contains(i) && i != id && self.lists[i].list_id
1140 != 0 implies self.lists[i].list_id != new_id by {
1141 assert(old_self.lists.dom().contains(i));
1142 assert(old_self.lists[i] == self.lists[i]);
1143 if old_self.lists[id].list_id != 0 {
1144 assert(new_id == old_self.lists[id].list_id);
1146 } else {
1147 assert(used.contains(self.lists[i].list_id));
1148 }
1149 };
1150
1151 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1153 &&& self.lists[i].inv()
1154 &&& self.lists[i].relate_region(self.regions)
1155 } by {
1156 if i != id {
1157 assert(old_self.lists.dom().contains(i));
1158 assert(old_self.lists[i] == self.lists[i]);
1159 assert(old_self.lists[i].relate_region(old_regions));
1160 if self.lists[i].list.len() > 0 {
1161 assert(self.lists[i].list_id != new_id);
1162 }
1163 }
1164 };
1165
1166 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1169 &&& self.loose[lid2].inv()
1170 &&& self.loose[lid2].global_inv(self.regions)
1171 &&& self.loose[lid2].frame_link_inv(self.regions)
1172 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1173 == 0
1174 } by {
1175 assert(lid2 != lid);
1176 assert(old_self.loose.dom().contains(lid2));
1177 assert(old_self.loose[lid2] == self.loose[lid2]);
1178 assert(old_self.loose[lid2].global_inv(old_regions));
1179 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1180 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1181 == 0);
1182 assert(self.loose[lid2].slot_index != fidx);
1183 };
1184
1185 assert forall|i1: ListId, i2: ListId| #[trigger]
1187 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1188 && self.lists[i1].list.len() > 0 && self.lists[i2].list.len() > 0
1189 && self.lists[i1].list_id == self.lists[i2].list_id implies i1 == i2 by {
1190 if i1 != id && i2 != id {
1191 assert(old_self.lists[i1] == self.lists[i1]);
1192 assert(old_self.lists[i2] == self.lists[i2]);
1193 } else if i1 == id && i2 != id {
1194 assert(self.lists[i2].list_id != new_id);
1195 } else if i2 == id && i1 != id {
1196 assert(self.lists[i1].list_id != new_id);
1197 }
1198 };
1199
1200 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1202 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1203 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1204 assert(old_self.loose.dom().contains(l1));
1205 assert(old_self.loose.dom().contains(l2));
1206 };
1207
1208 assert(self.cursors == old_self.cursors);
1216 assert(self.lists.dom() =~= old_self.lists.dom());
1217 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1218 &&& self.cursors[cid].list_own.inv()
1219 &&& self.cursors[cid].wf_with_region(self.regions)
1220 } by {
1221 assert(old_self.cursors.dom().contains(cid));
1222 assert(old_self.cursors[cid].wf_with_region(old_regions));
1223 assert(self.cursors[cid].list_own.relate_region(old_regions));
1224 if old_self.lists[id].list_id != 0 {
1225 assert(new_id == old_self.lists[id].list_id);
1226 } else {
1227 assert(used.contains(self.cursors[cid].list_own.list_id));
1228 }
1229 assert(self.cursors[cid].list_own.list_id != new_id);
1230 assert(self.cursors[cid].list_own.relate_region(self.regions));
1231 };
1232 assert forall|id2: ListId, cid: CursorId| #[trigger]
1233 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1234 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1235 && self.lists[id2].list_id != 0 implies false by {
1236 assert(old_self.cursors.dom().contains(cid));
1237 if id2 == id {
1238 assert(self.lists[id].list_id == new_id);
1239 if old_self.lists[id].list_id != 0 {
1240 assert(new_id == old_self.lists[id].list_id);
1241 } else {
1242 assert(used.contains(self.cursors[cid].list_own.list_id));
1243 }
1244 } else {
1245 assert(old_self.lists.dom().contains(id2));
1246 assert(old_self.lists[id2] == self.lists[id2]);
1247 }
1248 };
1249 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1250 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1251 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1252 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1253 assert(old_self.cursors.dom().contains(cid1));
1254 assert(old_self.cursors.dom().contains(cid2));
1255 };
1256 }
1257
1258 pub proof fn step_pop_front(tracked &mut self, id: ListId) -> (res: Option<LooseId>)
1262 requires
1263 old(self).inv(),
1264 old(self).lists.dom().contains(id),
1265 ensures
1266 final(self).inv(),
1267 old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),
1268 old(self).lists[id].list.len() > 0 ==> res is Some,
1269 {
1270 if self.lists[id].list.len() == 0 {
1271 Option::None
1274 } else {
1275 let ghost old_self = *self;
1276 let ghost old_regions = self.regions;
1277 let ghost popped_idx = self.lists[id].slot_index_at(0);
1278 let ghost old_list_id = self.lists[id].list_id;
1279 assert(self.lists[id].relate_region(self.regions));
1281
1282 let tracked mut owner = self.lists.tracked_remove(id);
1283 let tracked frame_own = tracked_pop_front_embedded(&mut self.regions, &mut owner);
1284 self.lists.tracked_insert(id, owner);
1285 let ghost new_loose = fresh_loose_id(self.loose);
1286 lemma_fresh_loose_id_not_in_dom(self.loose);
1287 self.loose.tracked_insert(new_loose, frame_own);
1288
1289 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1290 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
1291 assert(self.lists[id].list_id == old_list_id);
1292 assert(frame_own.slot_index == popped_idx);
1293
1294 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1296 &&& self.lists[i].inv()
1297 &&& self.lists[i].relate_region(self.regions)
1298 } by {
1299 if i != id {
1300 assert(old_self.lists.dom().contains(i));
1301 assert(old_self.lists[i] == self.lists[i]);
1302 assert(old_self.lists[i].relate_region(old_regions));
1303 if self.lists[i].list.len() > 0 {
1304 assert(self.lists[i].list_id != old_list_id);
1307 }
1308 }
1309 };
1310
1311 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1313 &&& self.loose[lid2].inv()
1314 &&& self.loose[lid2].global_inv(self.regions)
1315 &&& self.loose[lid2].frame_link_inv(self.regions)
1316 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1317 == 0
1318 } by {
1319 if lid2 != new_loose {
1320 assert(old_self.loose.dom().contains(lid2));
1321 assert(old_self.loose[lid2] == self.loose[lid2]);
1322 assert(old_self.loose[lid2].global_inv(old_regions));
1323 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1324 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1325 == 0);
1326 }
1327 };
1328
1329 assert forall|i1: ListId, i2: ListId| #[trigger]
1331 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1332 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1333 != 0 implies i1 == i2 by {
1334 assert(old_self.lists.dom().contains(i1));
1335 assert(old_self.lists.dom().contains(i2));
1336 assert(self.lists[i1].list_id == old_self.lists[i1].list_id);
1337 assert(self.lists[i2].list_id == old_self.lists[i2].list_id);
1338 };
1339
1340 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1342 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1343 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1344 if l1 == new_loose && l2 != new_loose {
1345 assert(old_self.loose.dom().contains(l2));
1346 assert(self.loose[l2].slot_index != popped_idx);
1347 } else if l2 == new_loose && l1 != new_loose {
1348 assert(old_self.loose.dom().contains(l1));
1349 assert(self.loose[l1].slot_index != popped_idx);
1350 } else if l1 != new_loose && l2 != new_loose {
1351 assert(old_self.loose.dom().contains(l1));
1352 assert(old_self.loose.dom().contains(l2));
1353 }
1354 };
1355
1356 assert(self.cursors == old_self.cursors);
1361 assert(self.lists.dom() =~= old_self.lists.dom());
1362 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1363 &&& self.cursors[cid].list_own.inv()
1364 &&& self.cursors[cid].wf_with_region(self.regions)
1365 } by {
1366 assert(old_self.cursors.dom().contains(cid));
1367 assert(old_self.cursors[cid].wf_with_region(old_regions));
1368 assert(self.cursors[cid].list_own.relate_region(old_regions));
1369 assert(old_self.lists.dom().contains(id));
1370 assert(old_self.lists[id].list_id == old_list_id);
1371 assert(self.cursors[cid].list_own.list_id != old_list_id);
1372 assert(self.cursors[cid].list_own.relate_region(self.regions));
1373 };
1374 assert forall|id2: ListId, cid: CursorId| #[trigger]
1375 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1376 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1377 && self.lists[id2].list_id != 0 implies false by {
1378 assert(old_self.cursors.dom().contains(cid));
1379 assert(old_self.lists.dom().contains(id2));
1380 assert(old_self.lists[id2].list_id == self.lists[id2].list_id);
1381 };
1382 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1383 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1384 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1385 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1386 assert(old_self.cursors.dom().contains(cid1));
1387 assert(old_self.cursors.dom().contains(cid2));
1388 };
1389 Option::Some(new_loose)
1390 }
1391 }
1392
1393 pub proof fn step_push_back(tracked &mut self, id: ListId, lid: LooseId)
1397 requires
1398 old(self).inv(),
1399 old(self).lists.dom().contains(id),
1400 old(self).loose.dom().contains(lid),
1401 ensures
1402 final(self).inv(),
1403 {
1404 let ghost old_self = *self;
1405 let ghost old_regions = self.regions;
1406 let ghost fidx = self.loose[lid].slot_index;
1407 let ghost used = Set::<u64>::full().unwrap().filter(
1408 |x: u64|
1409 (exists|i: ListId| #[trigger]
1410 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
1411 || (exists|cid: CursorId| #[trigger]
1412 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
1413 == x),
1414 );
1415 assert(self.lists[id].relate_region(self.regions));
1416 assert(self.loose[lid].global_inv(self.regions));
1417 assert(self.loose[lid].frame_link_inv(self.regions));
1418 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
1419
1420 let tracked mut owner = self.lists.tracked_remove(id);
1421 let tracked mut frame_own = self.loose.tracked_remove(lid);
1422 lemma_push_back_embedded(&mut self.regions, &mut owner, &mut frame_own, used);
1423 self.lists.tracked_insert(id, owner);
1424 assert(self.loose =~= old_self.loose.remove(lid));
1425 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1426 let ghost new_id = self.lists[id].list_id;
1427
1428 assert forall|i: ListId| #[trigger]
1429 self.lists.dom().contains(i) && i != id && self.lists[i].list_id
1430 != 0 implies self.lists[i].list_id != new_id by {
1431 assert(old_self.lists.dom().contains(i));
1432 assert(old_self.lists[i] == self.lists[i]);
1433 if old_self.lists[id].list_id != 0 {
1434 assert(new_id == old_self.lists[id].list_id);
1435 } else {
1436 assert(used.contains(self.lists[i].list_id));
1437 }
1438 };
1439
1440 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1441 &&& self.lists[i].inv()
1442 &&& self.lists[i].relate_region(self.regions)
1443 } by {
1444 if i != id {
1445 assert(old_self.lists.dom().contains(i));
1446 assert(old_self.lists[i] == self.lists[i]);
1447 assert(old_self.lists[i].relate_region(old_regions));
1448 if self.lists[i].list.len() > 0 {
1449 assert(self.lists[i].list_id != new_id);
1450 }
1451 }
1452 };
1453
1454 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1455 &&& self.loose[lid2].inv()
1456 &&& self.loose[lid2].global_inv(self.regions)
1457 &&& self.loose[lid2].frame_link_inv(self.regions)
1458 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1459 == 0
1460 } by {
1461 assert(lid2 != lid);
1462 assert(old_self.loose.dom().contains(lid2));
1463 assert(old_self.loose[lid2] == self.loose[lid2]);
1464 assert(old_self.loose[lid2].global_inv(old_regions));
1465 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1466 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1467 == 0);
1468 assert(self.loose[lid2].slot_index != fidx);
1469 };
1470
1471 assert forall|i1: ListId, i2: ListId| #[trigger]
1472 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1473 && self.lists[i1].list.len() > 0 && self.lists[i2].list.len() > 0
1474 && self.lists[i1].list_id == self.lists[i2].list_id implies i1 == i2 by {
1475 if i1 != id && i2 != id {
1476 assert(old_self.lists[i1] == self.lists[i1]);
1477 assert(old_self.lists[i2] == self.lists[i2]);
1478 } else if i1 == id && i2 != id {
1479 assert(self.lists[i2].list_id != new_id);
1480 } else if i2 == id && i1 != id {
1481 assert(self.lists[i1].list_id != new_id);
1482 }
1483 };
1484
1485 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1486 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1487 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1488 assert(old_self.loose.dom().contains(l1));
1489 assert(old_self.loose.dom().contains(l2));
1490 };
1491
1492 assert(self.cursors == old_self.cursors);
1500 assert(self.lists.dom() =~= old_self.lists.dom());
1501 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1502 &&& self.cursors[cid].list_own.inv()
1503 &&& self.cursors[cid].wf_with_region(self.regions)
1504 } by {
1505 assert(old_self.cursors.dom().contains(cid));
1506 assert(old_self.cursors[cid].wf_with_region(old_regions));
1507 assert(self.cursors[cid].list_own.relate_region(old_regions));
1508 if old_self.lists[id].list_id != 0 {
1509 assert(new_id == old_self.lists[id].list_id);
1510 } else {
1511 assert(used.contains(self.cursors[cid].list_own.list_id));
1512 }
1513 assert(self.cursors[cid].list_own.list_id != new_id);
1514 assert(self.cursors[cid].list_own.relate_region(self.regions));
1515 };
1516 assert forall|id2: ListId, cid: CursorId| #[trigger]
1517 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1518 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1519 && self.lists[id2].list_id != 0 implies false by {
1520 assert(old_self.cursors.dom().contains(cid));
1521 if id2 == id {
1522 assert(self.lists[id].list_id == new_id);
1523 if old_self.lists[id].list_id != 0 {
1524 assert(new_id == old_self.lists[id].list_id);
1525 } else {
1526 assert(used.contains(self.cursors[cid].list_own.list_id));
1527 }
1528 } else {
1529 assert(old_self.lists.dom().contains(id2));
1530 assert(old_self.lists[id2] == self.lists[id2]);
1531 }
1532 };
1533 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1534 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1535 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1536 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1537 assert(old_self.cursors.dom().contains(cid1));
1538 assert(old_self.cursors.dom().contains(cid2));
1539 };
1540 }
1541
1542 pub proof fn step_pop_back(tracked &mut self, id: ListId) -> (res: Option<LooseId>)
1546 requires
1547 old(self).inv(),
1548 old(self).lists.dom().contains(id),
1549 ensures
1550 final(self).inv(),
1551 old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),
1552 old(self).lists[id].list.len() > 0 ==> res is Some,
1553 {
1554 if self.lists[id].list.len() == 0 {
1555 Option::None
1558 } else {
1559 let ghost old_self = *self;
1560 let ghost old_regions = self.regions;
1561 let ghost popped_idx = self.lists[id].slot_index_at(self.lists[id].list.len() - 1);
1562 let ghost old_list_id = self.lists[id].list_id;
1563 assert(self.lists[id].relate_region(self.regions));
1564
1565 let tracked mut owner = self.lists.tracked_remove(id);
1566 let tracked frame_own = tracked_pop_back_embedded(&mut self.regions, &mut owner);
1567 self.lists.tracked_insert(id, owner);
1568 let ghost new_loose = fresh_loose_id(self.loose);
1569 lemma_fresh_loose_id_not_in_dom(self.loose);
1570 self.loose.tracked_insert(new_loose, frame_own);
1571
1572 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1573 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
1574 assert(self.lists[id].list_id == old_list_id);
1575 assert(frame_own.slot_index == popped_idx);
1576
1577 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1578 &&& self.lists[i].inv()
1579 &&& self.lists[i].relate_region(self.regions)
1580 } by {
1581 if i != id {
1582 assert(old_self.lists.dom().contains(i));
1583 assert(old_self.lists[i] == self.lists[i]);
1584 assert(old_self.lists[i].relate_region(old_regions));
1585 if self.lists[i].list.len() > 0 {
1586 assert(self.lists[i].list_id != old_list_id);
1587 }
1588 }
1589 };
1590
1591 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1592 &&& self.loose[lid2].inv()
1593 &&& self.loose[lid2].global_inv(self.regions)
1594 &&& self.loose[lid2].frame_link_inv(self.regions)
1595 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1596 == 0
1597 } by {
1598 if lid2 != new_loose {
1599 assert(old_self.loose.dom().contains(lid2));
1600 assert(old_self.loose[lid2] == self.loose[lid2]);
1601 assert(old_self.loose[lid2].global_inv(old_regions));
1602 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1603 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1604 == 0);
1605 }
1606 };
1607
1608 assert forall|i1: ListId, i2: ListId| #[trigger]
1609 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1610 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1611 != 0 implies i1 == i2 by {
1612 assert(old_self.lists.dom().contains(i1));
1613 assert(old_self.lists.dom().contains(i2));
1614 assert(self.lists[i1].list_id == old_self.lists[i1].list_id);
1615 assert(self.lists[i2].list_id == old_self.lists[i2].list_id);
1616 };
1617
1618 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1619 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1620 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1621 if l1 == new_loose && l2 != new_loose {
1622 assert(old_self.loose.dom().contains(l2));
1623 assert(self.loose[l2].slot_index != popped_idx);
1624 } else if l2 == new_loose && l1 != new_loose {
1625 assert(old_self.loose.dom().contains(l1));
1626 assert(self.loose[l1].slot_index != popped_idx);
1627 } else if l1 != new_loose && l2 != new_loose {
1628 assert(old_self.loose.dom().contains(l1));
1629 assert(old_self.loose.dom().contains(l2));
1630 }
1631 };
1632
1633 assert(self.cursors == old_self.cursors);
1638 assert(self.lists.dom() =~= old_self.lists.dom());
1639 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1640 &&& self.cursors[cid].list_own.inv()
1641 &&& self.cursors[cid].wf_with_region(self.regions)
1642 } by {
1643 assert(old_self.cursors.dom().contains(cid));
1644 assert(old_self.cursors[cid].wf_with_region(old_regions));
1645 assert(self.cursors[cid].list_own.relate_region(old_regions));
1646 assert(old_self.lists.dom().contains(id));
1647 assert(old_self.lists[id].list_id == old_list_id);
1648 assert(self.cursors[cid].list_own.list_id != old_list_id);
1649 assert(self.cursors[cid].list_own.relate_region(self.regions));
1650 };
1651 assert forall|id2: ListId, cid: CursorId| #[trigger]
1652 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1653 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1654 && self.lists[id2].list_id != 0 implies false by {
1655 assert(old_self.cursors.dom().contains(cid));
1656 assert(old_self.lists.dom().contains(id2));
1657 assert(old_self.lists[id2].list_id == self.lists[id2].list_id);
1658 };
1659 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1660 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1661 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1662 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1663 assert(old_self.cursors.dom().contains(cid1));
1664 assert(old_self.cursors.dom().contains(cid2));
1665 };
1666 Option::Some(new_loose)
1667 }
1668 }
1669
1670 pub proof fn step_insert_before_at(tracked &mut self, id: ListId, n: int, lid: LooseId)
1675 requires
1676 old(self).inv(),
1677 old(self).lists.dom().contains(id),
1678 old(self).loose.dom().contains(lid),
1679 0 <= n <= old(self).lists[id].list.len(),
1680 ensures
1681 final(self).inv(),
1682 {
1683 let ghost old_self = *self;
1684 let ghost old_regions = self.regions;
1685 let ghost fidx = self.loose[lid].slot_index;
1686 let ghost used = Set::<u64>::full().unwrap().filter(
1687 |x: u64|
1688 (exists|i: ListId| #[trigger]
1689 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
1690 || (exists|cid: CursorId| #[trigger]
1691 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
1692 == x),
1693 );
1694 assert(self.lists[id].relate_region(self.regions));
1695 assert(self.loose[lid].global_inv(self.regions));
1696 assert(self.loose[lid].frame_link_inv(self.regions));
1697 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
1698
1699 let tracked mut owner = self.lists.tracked_remove(id);
1700 let tracked mut frame_own = self.loose.tracked_remove(lid);
1701 insert_before_at_embedded(&mut self.regions, &mut owner, &mut frame_own, n, used);
1702 self.lists.tracked_insert(id, owner);
1703 assert(self.loose =~= old_self.loose.remove(lid));
1704 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1705 let ghost new_id = self.lists[id].list_id;
1706
1707 assert forall|i: ListId| #[trigger]
1708 self.lists.dom().contains(i) && i != id && self.lists[i].list_id
1709 != 0 implies self.lists[i].list_id != new_id by {
1710 assert(old_self.lists.dom().contains(i));
1711 assert(old_self.lists[i] == self.lists[i]);
1712 if old_self.lists[id].list_id != 0 {
1713 assert(new_id == old_self.lists[id].list_id);
1714 } else {
1715 assert(used.contains(self.lists[i].list_id));
1716 }
1717 };
1718
1719 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1720 &&& self.lists[i].inv()
1721 &&& self.lists[i].relate_region(self.regions)
1722 } by {
1723 if i != id {
1724 assert(old_self.lists.dom().contains(i));
1725 assert(old_self.lists[i] == self.lists[i]);
1726 assert(old_self.lists[i].relate_region(old_regions));
1727 if self.lists[i].list.len() > 0 {
1728 assert(self.lists[i].list_id != new_id);
1729 }
1730 }
1731 };
1732
1733 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1734 &&& self.loose[lid2].inv()
1735 &&& self.loose[lid2].global_inv(self.regions)
1736 &&& self.loose[lid2].frame_link_inv(self.regions)
1737 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1738 == 0
1739 } by {
1740 assert(lid2 != lid);
1741 assert(old_self.loose.dom().contains(lid2));
1742 assert(old_self.loose[lid2] == self.loose[lid2]);
1743 assert(old_self.loose[lid2].global_inv(old_regions));
1744 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1745 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1746 == 0);
1747 assert(self.loose[lid2].slot_index != fidx);
1748 };
1749
1750 assert forall|i1: ListId, i2: ListId| #[trigger]
1751 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1752 && self.lists[i1].list.len() > 0 && self.lists[i2].list.len() > 0
1753 && self.lists[i1].list_id == self.lists[i2].list_id implies i1 == i2 by {
1754 if i1 != id && i2 != id {
1755 assert(old_self.lists[i1] == self.lists[i1]);
1756 assert(old_self.lists[i2] == self.lists[i2]);
1757 } else if i1 == id && i2 != id {
1758 assert(self.lists[i2].list_id != new_id);
1759 } else if i2 == id && i1 != id {
1760 assert(self.lists[i1].list_id != new_id);
1761 }
1762 };
1763
1764 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1765 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1766 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1767 assert(old_self.loose.dom().contains(l1));
1768 assert(old_self.loose.dom().contains(l2));
1769 };
1770
1771 assert(self.cursors == old_self.cursors);
1779 assert(self.lists.dom() =~= old_self.lists.dom());
1780 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1781 &&& self.cursors[cid].list_own.inv()
1782 &&& self.cursors[cid].wf_with_region(self.regions)
1783 } by {
1784 assert(old_self.cursors.dom().contains(cid));
1785 assert(old_self.cursors[cid].wf_with_region(old_regions));
1786 assert(self.cursors[cid].list_own.relate_region(old_regions));
1787 if old_self.lists[id].list_id != 0 {
1788 assert(new_id == old_self.lists[id].list_id);
1789 } else {
1790 assert(used.contains(self.cursors[cid].list_own.list_id));
1791 }
1792 assert(self.cursors[cid].list_own.list_id != new_id);
1793 assert(self.cursors[cid].list_own.relate_region(self.regions));
1794 };
1795 assert forall|id2: ListId, cid: CursorId| #[trigger]
1796 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1797 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1798 && self.lists[id2].list_id != 0 implies false by {
1799 assert(old_self.cursors.dom().contains(cid));
1800 if id2 == id {
1801 assert(self.lists[id].list_id == new_id);
1802 if old_self.lists[id].list_id != 0 {
1803 assert(new_id == old_self.lists[id].list_id);
1804 } else {
1805 assert(used.contains(self.cursors[cid].list_own.list_id));
1806 }
1807 } else {
1808 assert(old_self.lists.dom().contains(id2));
1809 assert(old_self.lists[id2] == self.lists[id2]);
1810 }
1811 };
1812 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1813 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1814 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1815 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1816 assert(old_self.cursors.dom().contains(cid1));
1817 assert(old_self.cursors.dom().contains(cid2));
1818 };
1819 }
1820
1821 pub proof fn step_take_at(tracked &mut self, id: ListId, n: int) -> (res: Option<LooseId>)
1826 requires
1827 old(self).inv(),
1828 old(self).lists.dom().contains(id),
1829 ensures
1830 final(self).inv(),
1831 !(0 <= n < old(self).lists[id].list.len()) ==> res is None && *final(self) == *old(
1832 self,
1833 ),
1834 0 <= n < old(self).lists[id].list.len() ==> res is Some,
1835 {
1836 if !(0 <= n < self.lists[id].list.len()) {
1837 Option::None
1840 } else {
1841 let ghost old_self = *self;
1842 let ghost old_regions = self.regions;
1843 let ghost popped_idx = self.lists[id].slot_index_at(n);
1844 let ghost old_list_id = self.lists[id].list_id;
1845 assert(self.lists[id].relate_region(self.regions));
1846
1847 let tracked mut owner = self.lists.tracked_remove(id);
1848 let tracked frame_own = take_at_embedded(&mut self.regions, &mut owner, n);
1849 self.lists.tracked_insert(id, owner);
1850 let ghost new_loose = fresh_loose_id(self.loose);
1851 lemma_fresh_loose_id_not_in_dom(self.loose);
1852 self.loose.tracked_insert(new_loose, frame_own);
1853
1854 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1855 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
1856 assert(self.lists[id].list_id == old_list_id);
1857 assert(frame_own.slot_index == popped_idx);
1858
1859 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1860 &&& self.lists[i].inv()
1861 &&& self.lists[i].relate_region(self.regions)
1862 } by {
1863 if i != id {
1864 assert(old_self.lists.dom().contains(i));
1865 assert(old_self.lists[i] == self.lists[i]);
1866 assert(old_self.lists[i].relate_region(old_regions));
1867 if self.lists[i].list.len() > 0 {
1868 assert(self.lists[i].list_id != old_list_id);
1869 }
1870 }
1871 };
1872
1873 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1874 &&& self.loose[lid2].inv()
1875 &&& self.loose[lid2].global_inv(self.regions)
1876 &&& self.loose[lid2].frame_link_inv(self.regions)
1877 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1878 == 0
1879 } by {
1880 if lid2 != new_loose {
1881 assert(old_self.loose.dom().contains(lid2));
1882 assert(old_self.loose[lid2] == self.loose[lid2]);
1883 assert(old_self.loose[lid2].global_inv(old_regions));
1884 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1885 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1886 == 0);
1887 }
1888 };
1889
1890 assert forall|i1: ListId, i2: ListId| #[trigger]
1891 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1892 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1893 != 0 implies i1 == i2 by {
1894 assert(old_self.lists.dom().contains(i1));
1895 assert(old_self.lists.dom().contains(i2));
1896 assert(self.lists[i1].list_id == old_self.lists[i1].list_id);
1897 assert(self.lists[i2].list_id == old_self.lists[i2].list_id);
1898 };
1899
1900 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1901 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1902 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1903 if l1 == new_loose && l2 != new_loose {
1904 assert(old_self.loose.dom().contains(l2));
1905 assert(self.loose[l2].slot_index != popped_idx);
1906 } else if l2 == new_loose && l1 != new_loose {
1907 assert(old_self.loose.dom().contains(l1));
1908 assert(self.loose[l1].slot_index != popped_idx);
1909 } else if l1 != new_loose && l2 != new_loose {
1910 assert(old_self.loose.dom().contains(l1));
1911 assert(old_self.loose.dom().contains(l2));
1912 }
1913 };
1914
1915 assert(self.cursors == old_self.cursors);
1920 assert(self.lists.dom() =~= old_self.lists.dom());
1921 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1922 &&& self.cursors[cid].list_own.inv()
1923 &&& self.cursors[cid].wf_with_region(self.regions)
1924 } by {
1925 assert(old_self.cursors.dom().contains(cid));
1926 assert(old_self.cursors[cid].wf_with_region(old_regions));
1927 assert(self.cursors[cid].list_own.relate_region(old_regions));
1928 assert(old_self.lists.dom().contains(id));
1929 assert(old_self.lists[id].list_id == old_list_id);
1930 assert(self.cursors[cid].list_own.list_id != old_list_id);
1931 assert(self.cursors[cid].list_own.relate_region(self.regions));
1932 };
1933 assert forall|id2: ListId, cid: CursorId| #[trigger]
1934 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1935 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1936 && self.lists[id2].list_id != 0 implies false by {
1937 assert(old_self.cursors.dom().contains(cid));
1938 assert(old_self.lists.dom().contains(id2));
1939 assert(old_self.lists[id2].list_id == self.lists[id2].list_id);
1940 };
1941 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1942 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1943 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1944 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1945 assert(old_self.cursors.dom().contains(cid1));
1946 assert(old_self.cursors.dom().contains(cid2));
1947 };
1948 Option::Some(new_loose)
1949 }
1950 }
1951
1952 proof fn lemma_checkout_inv(old_self: Self, new_self: Self, id: ListId, index: int)
1962 requires
1963 old_self.inv(),
1964 old_self.lists.dom().contains(id),
1965 0 <= index <= old_self.lists[id].list.len(),
1966 new_self.regions == old_self.regions,
1967 new_self.loose == old_self.loose,
1968 new_self.lists == old_self.lists.remove(id),
1969 new_self.cursors == old_self.cursors.insert(
1970 id,
1971 CursorOwner::cursor_mut_at_owner(old_self.lists[id], index),
1972 ),
1973 ensures
1974 new_self.inv(),
1975 {
1976 assert forall|i: ListId| #[trigger] new_self.lists.dom().contains(i) implies {
1977 &&& new_self.lists[i].inv()
1978 &&& new_self.lists[i].relate_region(new_self.regions)
1979 } by {
1980 assert(i != id);
1981 assert(old_self.lists.dom().contains(i));
1982 assert(old_self.lists[i] == new_self.lists[i]);
1983 };
1984 assert forall|lid: LooseId| #[trigger] new_self.loose.dom().contains(lid) implies {
1985 &&& new_self.loose[lid].inv()
1986 &&& new_self.loose[lid].global_inv(new_self.regions)
1987 &&& new_self.loose[lid].frame_link_inv(new_self.regions)
1988 &&& new_self.regions.slot_owners[new_self.loose[lid].slot_index].inner_perms.in_list.value()
1989 == 0
1990 } by {
1991 assert(old_self.loose.dom().contains(lid));
1992 };
1993 assert forall|i1: ListId, i2: ListId| #[trigger]
1994 new_self.lists.dom().contains(i1) && #[trigger] new_self.lists.dom().contains(i2)
1995 && new_self.lists[i1].list_id == new_self.lists[i2].list_id
1996 && new_self.lists[i1].list_id != 0 implies i1 == i2 by {
1997 assert(old_self.lists.dom().contains(i1));
1998 assert(old_self.lists.dom().contains(i2));
1999 };
2000 assert forall|l1: LooseId, l2: LooseId| #[trigger]
2001 new_self.loose.dom().contains(l1) && #[trigger] new_self.loose.dom().contains(l2)
2002 && new_self.loose[l1].slot_index == new_self.loose[l2].slot_index implies l1
2003 == l2 by {
2004 assert(old_self.loose.dom().contains(l1));
2005 assert(old_self.loose.dom().contains(l2));
2006 };
2007 assert(new_self.lists.dom().disjoint(new_self.cursors.dom()));
2008 assert forall|cid: CursorId| #[trigger] new_self.cursors.dom().contains(cid) implies {
2009 &&& new_self.cursors[cid].list_own.inv()
2010 &&& new_self.cursors[cid].wf_with_region(new_self.regions)
2011 } by {
2012 if cid != id {
2013 assert(old_self.cursors.dom().contains(cid));
2014 } else {
2015 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2016 assert(old_self.lists[id].relate_region(old_self.regions));
2017 }
2018 };
2019 assert forall|id2: ListId, cid: CursorId| #[trigger]
2020 new_self.lists.dom().contains(id2) && #[trigger] new_self.cursors.dom().contains(cid)
2021 && new_self.lists[id2].list_id == new_self.cursors[cid].list_own.list_id
2022 && new_self.lists[id2].list_id != 0 implies false by {
2023 assert(id2 != id);
2024 assert(old_self.lists.dom().contains(id2));
2025 assert(old_self.lists[id2] == new_self.lists[id2]);
2026 if cid == id {
2027 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2028 assert(old_self.lists.dom().contains(id));
2029 } else {
2030 assert(old_self.cursors.dom().contains(cid));
2031 assert(old_self.cursors[cid] == new_self.cursors[cid]);
2032 }
2033 };
2034 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2035 new_self.cursors.dom().contains(cid1) && #[trigger] new_self.cursors.dom().contains(
2036 cid2,
2037 ) && new_self.cursors[cid1].list_own.list_id == new_self.cursors[cid2].list_own.list_id
2038 && new_self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2039 if cid1 == id && cid2 != id {
2040 assert(old_self.cursors.dom().contains(cid2));
2041 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2042 assert(old_self.lists.dom().contains(id));
2043 } else if cid2 == id && cid1 != id {
2044 assert(old_self.cursors.dom().contains(cid1));
2045 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2046 assert(old_self.lists.dom().contains(id));
2047 } else if cid1 != id && cid2 != id {
2048 assert(old_self.cursors.dom().contains(cid1));
2049 assert(old_self.cursors.dom().contains(cid2));
2050 }
2051 };
2052 }
2053
2054 proof fn lemma_checkin_inv(old_self: Self, new_self: Self, id: CursorId)
2058 requires
2059 old_self.inv(),
2060 old_self.cursors.dom().contains(id),
2061 new_self.regions == old_self.regions,
2062 new_self.loose == old_self.loose,
2063 new_self.cursors == old_self.cursors.remove(id),
2064 new_self.lists == old_self.lists.insert(id, old_self.cursors[id].list_own),
2065 ensures
2066 new_self.inv(),
2067 {
2068 assert(!old_self.lists.dom().contains(id));
2069 assert forall|i: ListId| #[trigger] new_self.lists.dom().contains(i) implies {
2070 &&& new_self.lists[i].inv()
2071 &&& new_self.lists[i].relate_region(new_self.regions)
2072 } by {
2073 if i == id {
2074 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2075 assert(old_self.cursors[id].wf_with_region(old_self.regions));
2076 } else {
2077 assert(old_self.lists.dom().contains(i));
2078 assert(old_self.lists[i] == new_self.lists[i]);
2079 }
2080 };
2081 assert forall|lid: LooseId| #[trigger] new_self.loose.dom().contains(lid) implies {
2082 &&& new_self.loose[lid].inv()
2083 &&& new_self.loose[lid].global_inv(new_self.regions)
2084 &&& new_self.loose[lid].frame_link_inv(new_self.regions)
2085 &&& new_self.regions.slot_owners[new_self.loose[lid].slot_index].inner_perms.in_list.value()
2086 == 0
2087 } by {
2088 assert(old_self.loose.dom().contains(lid));
2089 };
2090 assert forall|i1: ListId, i2: ListId| #[trigger]
2091 new_self.lists.dom().contains(i1) && #[trigger] new_self.lists.dom().contains(i2)
2092 && new_self.lists[i1].list_id == new_self.lists[i2].list_id
2093 && new_self.lists[i1].list_id != 0 implies i1 == i2 by {
2094 if i1 == id && i2 != id {
2098 assert(old_self.lists.dom().contains(i2));
2099 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2100 assert(old_self.cursors.dom().contains(id));
2101 } else if i2 == id && i1 != id {
2102 assert(old_self.lists.dom().contains(i1));
2103 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2104 assert(old_self.cursors.dom().contains(id));
2105 } else if i1 != id && i2 != id {
2106 assert(old_self.lists.dom().contains(i1));
2107 assert(old_self.lists.dom().contains(i2));
2108 }
2109 };
2110 assert forall|l1: LooseId, l2: LooseId| #[trigger]
2111 new_self.loose.dom().contains(l1) && #[trigger] new_self.loose.dom().contains(l2)
2112 && new_self.loose[l1].slot_index == new_self.loose[l2].slot_index implies l1
2113 == l2 by {
2114 assert(old_self.loose.dom().contains(l1));
2115 assert(old_self.loose.dom().contains(l2));
2116 };
2117 assert(new_self.lists.dom().disjoint(new_self.cursors.dom()));
2118 assert forall|cid: CursorId| #[trigger] new_self.cursors.dom().contains(cid) implies {
2119 &&& new_self.cursors[cid].list_own.inv()
2120 &&& new_self.cursors[cid].wf_with_region(new_self.regions)
2121 } by {
2122 assert(cid != id);
2123 assert(old_self.cursors.dom().contains(cid));
2124 assert(old_self.cursors[cid] == new_self.cursors[cid]);
2125 };
2126 assert forall|id2: ListId, cid: CursorId| #[trigger]
2127 new_self.lists.dom().contains(id2) && #[trigger] new_self.cursors.dom().contains(cid)
2128 && new_self.lists[id2].list_id == new_self.cursors[cid].list_own.list_id
2129 && new_self.lists[id2].list_id != 0 implies false by {
2130 assert(cid != id);
2131 assert(old_self.cursors.dom().contains(cid));
2132 assert(old_self.cursors[cid] == new_self.cursors[cid]);
2133 if id2 == id {
2134 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2135 assert(old_self.cursors.dom().contains(id));
2136 } else {
2137 assert(old_self.lists.dom().contains(id2));
2138 assert(old_self.lists[id2] == new_self.lists[id2]);
2139 }
2140 };
2141 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2142 new_self.cursors.dom().contains(cid1) && #[trigger] new_self.cursors.dom().contains(
2143 cid2,
2144 ) && new_self.cursors[cid1].list_own.list_id == new_self.cursors[cid2].list_own.list_id
2145 && new_self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2146 assert(old_self.cursors.dom().contains(cid1));
2147 assert(old_self.cursors.dom().contains(cid2));
2148 };
2149 }
2150
2151 proof fn lemma_revise_cursor_inv(old_self: Self, new_self: Self, id: CursorId)
2156 requires
2157 old_self.inv(),
2158 old_self.cursors.dom().contains(id),
2159 new_self.regions == old_self.regions,
2160 new_self.lists == old_self.lists,
2161 new_self.loose == old_self.loose,
2162 new_self.cursors.dom() == old_self.cursors.dom(),
2163 new_self.cursors[id].list_own == old_self.cursors[id].list_own,
2164 0 <= new_self.cursors[id].index <= new_self.cursors[id].list_own.list.len(),
2165 forall|c: CursorId| #[trigger]
2166 new_self.cursors.dom().contains(c) && c != id ==> new_self.cursors[c]
2167 == old_self.cursors[c],
2168 ensures
2169 new_self.inv(),
2170 {
2171 assert forall|i: ListId| #[trigger] new_self.lists.dom().contains(i) implies {
2172 &&& new_self.lists[i].inv()
2173 &&& new_self.lists[i].relate_region(new_self.regions)
2174 } by {
2175 assert(old_self.lists.dom().contains(i));
2176 };
2177 assert forall|lid: LooseId| #[trigger] new_self.loose.dom().contains(lid) implies {
2178 &&& new_self.loose[lid].inv()
2179 &&& new_self.loose[lid].global_inv(new_self.regions)
2180 &&& new_self.loose[lid].frame_link_inv(new_self.regions)
2181 &&& new_self.regions.slot_owners[new_self.loose[lid].slot_index].inner_perms.in_list.value()
2182 == 0
2183 } by {
2184 assert(old_self.loose.dom().contains(lid));
2185 };
2186 assert forall|i1: ListId, i2: ListId| #[trigger]
2187 new_self.lists.dom().contains(i1) && #[trigger] new_self.lists.dom().contains(i2)
2188 && new_self.lists[i1].list_id == new_self.lists[i2].list_id
2189 && new_self.lists[i1].list_id != 0 implies i1 == i2 by {
2190 assert(old_self.lists.dom().contains(i1));
2191 assert(old_self.lists.dom().contains(i2));
2192 };
2193 assert forall|l1: LooseId, l2: LooseId| #[trigger]
2194 new_self.loose.dom().contains(l1) && #[trigger] new_self.loose.dom().contains(l2)
2195 && new_self.loose[l1].slot_index == new_self.loose[l2].slot_index implies l1
2196 == l2 by {
2197 assert(old_self.loose.dom().contains(l1));
2198 assert(old_self.loose.dom().contains(l2));
2199 };
2200 assert(new_self.lists.dom().disjoint(new_self.cursors.dom()));
2201 assert forall|cid: CursorId| #[trigger] new_self.cursors.dom().contains(cid) implies {
2202 &&& new_self.cursors[cid].list_own.inv()
2203 &&& new_self.cursors[cid].wf_with_region(new_self.regions)
2204 } by {
2205 assert(old_self.cursors.dom().contains(cid));
2206 if cid != id {
2207 assert(new_self.cursors[cid] == old_self.cursors[cid]);
2208 } else {
2209 assert(new_self.cursors[id].list_own == old_self.cursors[id].list_own);
2210 assert(old_self.cursors[id].wf_with_region(old_self.regions));
2211 }
2212 };
2213 assert forall|id2: ListId, cid: CursorId| #[trigger]
2214 new_self.lists.dom().contains(id2) && #[trigger] new_self.cursors.dom().contains(cid)
2215 && new_self.lists[id2].list_id == new_self.cursors[cid].list_own.list_id
2216 && new_self.lists[id2].list_id != 0 implies false by {
2217 assert(old_self.lists.dom().contains(id2));
2218 assert(old_self.cursors.dom().contains(cid));
2219 assert(new_self.cursors[cid].list_own.list_id
2220 == old_self.cursors[cid].list_own.list_id);
2221 };
2222 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2223 new_self.cursors.dom().contains(cid1) && #[trigger] new_self.cursors.dom().contains(
2224 cid2,
2225 ) && new_self.cursors[cid1].list_own.list_id == new_self.cursors[cid2].list_own.list_id
2226 && new_self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2227 assert(old_self.cursors.dom().contains(cid1));
2228 assert(old_self.cursors.dom().contains(cid2));
2229 assert(new_self.cursors[cid1].list_own.list_id
2230 == old_self.cursors[cid1].list_own.list_id);
2231 assert(new_self.cursors[cid2].list_own.list_id
2232 == old_self.cursors[cid2].list_own.list_id);
2233 };
2234 }
2235
2236 pub proof fn step_cursor_front_mut(tracked &mut self, id: ListId)
2240 requires
2241 old(self).inv(),
2242 old(self).lists.dom().contains(id),
2243 ensures
2244 final(self).inv(),
2245 !final(self).lists.dom().contains(id),
2246 final(self).cursors.dom().contains(id),
2247 final(self).cursors[id] == CursorOwner::front_owner(old(self).lists[id]),
2248 {
2249 let ghost old_self = *self;
2250 let tracked owner = self.lists.tracked_remove(id);
2251 let tracked cur = CursorOwner::tracked_front_owner(owner);
2252 self.cursors.tracked_insert(id, cur);
2253 assert(self.lists =~= old_self.lists.remove(id));
2254 assert(self.cursors =~= old_self.cursors.insert(
2255 id,
2256 CursorOwner::cursor_mut_at_owner(old_self.lists[id], 0),
2257 ));
2258 Self::lemma_checkout_inv(old_self, *self, id, 0);
2259 }
2260
2261 pub proof fn step_cursor_back_mut(tracked &mut self, id: ListId)
2264 requires
2265 old(self).inv(),
2266 old(self).lists.dom().contains(id),
2267 ensures
2268 final(self).inv(),
2269 !final(self).lists.dom().contains(id),
2270 final(self).cursors.dom().contains(id),
2271 final(self).cursors[id] == CursorOwner::back_owner(old(self).lists[id]),
2272 {
2273 let ghost old_self = *self;
2274 let tracked owner = self.lists.tracked_remove(id);
2275 let ghost bidx = CursorOwner::back_owner(owner).index;
2276 let tracked cur = CursorOwner::tracked_back_owner(owner);
2277 self.cursors.tracked_insert(id, cur);
2278 assert(self.lists =~= old_self.lists.remove(id));
2279 assert(self.cursors =~= old_self.cursors.insert(
2280 id,
2281 CursorOwner::cursor_mut_at_owner(old_self.lists[id], bidx),
2282 ));
2283 Self::lemma_checkout_inv(old_self, *self, id, bidx);
2284 }
2285
2286 pub proof fn step_cursor_mut_at(tracked &mut self, id: ListId, frame: Paddr) -> (res: bool)
2293 requires
2294 old(self).inv(),
2295 old(self).lists.dom().contains(id),
2296 ensures
2297 final(self).inv(),
2298 res == (exists|i: int|
2300 0 <= i < old(self).lists[id].list.len() && old(self).lists[id].slot_index_at(i)
2301 == frame_to_index(frame)),
2302 res ==> !final(self).lists.dom().contains(id) && final(self).cursors.dom().contains(id)
2305 && exists|i: int|
2306 0 <= i < old(self).lists[id].list.len() && old(self).lists[id].slot_index_at(i)
2307 == frame_to_index(frame) && final(self).cursors[id]
2308 == CursorOwner::cursor_mut_at_owner(old(self).lists[id], i),
2309 !res ==> *final(self) == *old(self),
2311 {
2312 if exists|i: int|
2313 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i) == frame_to_index(
2314 frame,
2315 ) {
2316 let ghost index = choose|i: int|
2317 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i)
2318 == frame_to_index(frame);
2319 let ghost old_self = *self;
2320 let tracked owner = self.lists.tracked_remove(id);
2321 let tracked cur = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
2322 self.cursors.tracked_insert(id, cur);
2323 assert(self.lists =~= old_self.lists.remove(id));
2324 assert(self.cursors =~= old_self.cursors.insert(
2325 id,
2326 CursorOwner::cursor_mut_at_owner(old_self.lists[id], index),
2327 ));
2328 Self::lemma_checkout_inv(old_self, *self, id, index);
2329 true
2330 } else {
2331 false
2332 }
2333 }
2334
2335 pub proof fn step_move_next(tracked &mut self, id: CursorId)
2338 requires
2339 old(self).inv(),
2340 old(self).cursors.dom().contains(id),
2341 ensures
2342 final(self).inv(),
2343 final(self).regions == old(self).regions,
2344 final(self).cursors[id] == old(self).cursors[id].move_next_owner_spec(),
2345 {
2346 let ghost old_self = *self;
2347 let tracked cur = self.cursors.tracked_remove(id);
2348 let ghost ni = cur.move_next_owner_spec().index;
2349 let tracked CursorOwner { list_own, index: _ } = cur;
2350 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(list_own, ni);
2351 self.cursors.tracked_insert(id, cur2);
2352 assert(self.cursors[id] == old_self.cursors[id].move_next_owner_spec());
2353 assert(self.cursors.dom() =~= old_self.cursors.dom());
2354 Self::lemma_revise_cursor_inv(old_self, *self, id);
2355 }
2356
2357 pub proof fn step_move_prev(tracked &mut self, id: CursorId)
2360 requires
2361 old(self).inv(),
2362 old(self).cursors.dom().contains(id),
2363 ensures
2364 final(self).inv(),
2365 final(self).regions == old(self).regions,
2366 final(self).cursors[id] == old(self).cursors[id].move_prev_owner_spec(),
2367 {
2368 let ghost old_self = *self;
2369 let tracked cur = self.cursors.tracked_remove(id);
2370 let ghost ni = cur.move_prev_owner_spec().index;
2371 let tracked CursorOwner { list_own, index: _ } = cur;
2372 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(list_own, ni);
2373 self.cursors.tracked_insert(id, cur2);
2374 assert(self.cursors[id] == old_self.cursors[id].move_prev_owner_spec());
2375 assert(self.cursors.dom() =~= old_self.cursors.dom());
2376 Self::lemma_revise_cursor_inv(old_self, *self, id);
2377 }
2378
2379 pub proof fn step_current_meta(tracked &self, id: CursorId) -> (res: Option<LinkOwner>)
2383 requires
2384 self.inv(),
2385 self.cursors.dom().contains(id),
2386 ensures
2387 res == self.cursors[id].current(),
2388 res.is_some() <==> 0 <= self.cursors[id].index < self.cursors[id].length(),
2389 {
2390 self.cursors[id].current()
2391 }
2392
2393 pub proof fn step_as_list(tracked &self, id: CursorId) -> (res: Seq<LinkOwner>)
2399 requires
2400 self.inv(),
2401 self.cursors.dom().contains(id),
2402 ensures
2403 res == self.cursors[id].list_own.list,
2404 res.len() == self.cursors[id].length(),
2405 {
2406 self.cursors[id].list_own.list
2407 }
2408
2409 pub proof fn step_cursor_drop(tracked &mut self, id: CursorId)
2413 requires
2414 old(self).inv(),
2415 old(self).cursors.dom().contains(id),
2416 ensures
2417 final(self).inv(),
2418 !final(self).cursors.dom().contains(id),
2419 final(self).lists.dom().contains(id),
2420 final(self).lists[id] == old(self).cursors[id].list_own,
2421 {
2422 let ghost old_self = *self;
2423 let tracked cur = self.cursors.tracked_remove(id);
2424 let tracked CursorOwner { list_own, index: _ } = cur;
2425 self.lists.tracked_insert(id, list_own);
2426 assert(self.cursors =~= old_self.cursors.remove(id));
2427 assert(self.lists =~= old_self.lists.insert(id, old_self.cursors[id].list_own));
2428 Self::lemma_checkin_inv(old_self, *self, id);
2429 }
2430
2431 pub proof fn step_cursor_insert_before(tracked &mut self, id: CursorId, lid: LooseId)
2438 requires
2439 old(self).inv(),
2440 old(self).cursors.dom().contains(id),
2441 old(self).loose.dom().contains(lid),
2442 ensures
2443 final(self).inv(),
2444 {
2445 let ghost old_self = *self;
2446 let ghost old_regions = self.regions;
2447 let ghost fidx = self.loose[lid].slot_index;
2448 let ghost n = self.cursors[id].index;
2449 let ghost used = Set::<u64>::full().unwrap().filter(
2451 |x: u64|
2452 (exists|i: ListId| #[trigger]
2453 old_self.lists.dom().contains(i) && old_self.lists[i].list_id == x) || (exists|
2454 cid: CursorId,
2455 | #[trigger]
2456 old_self.cursors.dom().contains(cid) && cid != id
2457 && old_self.cursors[cid].list_own.list_id == x),
2458 );
2459 assert(self.cursors[id].wf_with_region(self.regions));
2460 assert(self.cursors[id].list_own.relate_region(self.regions));
2461 assert(self.loose[lid].global_inv(self.regions));
2462 assert(self.loose[lid].frame_link_inv(self.regions));
2463 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
2464
2465 let tracked cur = self.cursors.tracked_remove(id);
2466 let tracked CursorOwner { list_own: mut owner, index: _ } = cur;
2467 let tracked mut frame_own = self.loose.tracked_remove(lid);
2468 insert_before_at_embedded(&mut self.regions, &mut owner, &mut frame_own, n, used);
2469 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(owner, n + 1);
2470 self.cursors.tracked_insert(id, cur2);
2471 assert(self.loose =~= old_self.loose.remove(lid));
2472 assert(self.cursors =~= old_self.cursors.remove(id).insert(id, cur2));
2473 let ghost new_id = self.cursors[id].list_own.list_id;
2474 assert(self.cursors[id].list_own == owner);
2475
2476 assert forall|i: ListId| #[trigger]
2480 old_self.lists.dom().contains(i) && self.lists[i].list_id
2481 != 0 implies self.lists[i].list_id != new_id by {
2482 if old_self.cursors[id].list_own.list_id != 0 {
2483 assert(new_id == old_self.cursors[id].list_own.list_id);
2484 assert(old_self.cursors.dom().contains(id));
2485 } else {
2486 assert(used.contains(self.lists[i].list_id));
2487 }
2488 };
2489 assert forall|cid: CursorId| #[trigger]
2490 old_self.cursors.dom().contains(cid) && cid != id
2491 && old_self.cursors[cid].list_own.list_id
2492 != 0 implies old_self.cursors[cid].list_own.list_id != new_id by {
2493 if old_self.cursors[id].list_own.list_id != 0 {
2494 assert(new_id == old_self.cursors[id].list_own.list_id);
2495 } else {
2496 assert(used.contains(old_self.cursors[cid].list_own.list_id));
2497 }
2498 };
2499
2500 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
2502 &&& self.lists[i].inv()
2503 &&& self.lists[i].relate_region(self.regions)
2504 } by {
2505 assert(old_self.lists.dom().contains(i));
2506 assert(old_self.lists[i] == self.lists[i]);
2507 assert(old_self.lists[i].relate_region(old_regions));
2508 assert(self.lists[i].list_id != new_id);
2509 assert(self.lists[i].relate_region(self.regions));
2510 };
2511
2512 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
2514 &&& self.loose[lid2].inv()
2515 &&& self.loose[lid2].global_inv(self.regions)
2516 &&& self.loose[lid2].frame_link_inv(self.regions)
2517 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2518 == 0
2519 } by {
2520 assert(lid2 != lid);
2521 assert(old_self.loose.dom().contains(lid2));
2522 assert(old_self.loose[lid2] == self.loose[lid2]);
2523 assert(old_self.loose[lid2].global_inv(old_regions));
2524 assert(old_self.loose[lid2].frame_link_inv(old_regions));
2525 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2526 == 0);
2527 assert(self.loose[lid2].slot_index != fidx);
2528 };
2529
2530 assert(self.lists.dom() =~= old_self.lists.dom());
2532 assert(self.cursors.dom() =~= old_self.cursors.dom());
2533 assert(self.lists.dom().disjoint(self.cursors.dom()));
2534
2535 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
2537 &&& self.cursors[cid].list_own.inv()
2538 &&& self.cursors[cid].wf_with_region(self.regions)
2539 } by {
2540 if cid == id {
2541 assert(self.cursors[id].list_own == owner);
2542 assert(self.cursors[id].index == n + 1);
2543 assert(owner.list.len() == old_self.cursors[id].list_own.list.len() + 1);
2544 } else {
2545 assert(old_self.cursors.dom().contains(cid));
2546 assert(old_self.cursors[cid] == self.cursors[cid]);
2547 assert(old_self.cursors[cid].wf_with_region(old_regions));
2548 assert(self.cursors[cid].list_own.relate_region(old_regions));
2549 assert(self.cursors[cid].list_own.list_id != new_id);
2550 assert(self.cursors[cid].list_own.relate_region(self.regions));
2551 }
2552 };
2553
2554 assert forall|id2: ListId, cid: CursorId| #[trigger]
2556 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
2557 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
2558 && self.lists[id2].list_id != 0 implies false by {
2559 assert(old_self.lists.dom().contains(id2));
2560 assert(old_self.lists[id2] == self.lists[id2]);
2561 if cid == id {
2562 assert(self.cursors[id].list_own.list_id == new_id);
2563 assert(self.lists[id2].list_id != new_id);
2564 } else {
2565 assert(old_self.cursors.dom().contains(cid));
2566 assert(old_self.cursors[cid] == self.cursors[cid]);
2567 }
2568 };
2569
2570 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2572 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
2573 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
2574 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2575 if cid1 == id && cid2 != id {
2576 assert(self.cursors[id].list_own.list_id == new_id);
2577 assert(old_self.cursors.dom().contains(cid2));
2578 assert(old_self.cursors[cid2] == self.cursors[cid2]);
2579 assert(self.cursors[cid2].list_own.list_id != new_id);
2580 } else if cid2 == id && cid1 != id {
2581 assert(self.cursors[id].list_own.list_id == new_id);
2582 assert(old_self.cursors.dom().contains(cid1));
2583 assert(old_self.cursors[cid1] == self.cursors[cid1]);
2584 assert(self.cursors[cid1].list_own.list_id != new_id);
2585 } else if cid1 != id && cid2 != id {
2586 assert(old_self.cursors.dom().contains(cid1));
2587 assert(old_self.cursors.dom().contains(cid2));
2588 }
2589 };
2590 }
2591
2592 pub proof fn step_cursor_take_current(tracked &mut self, id: CursorId) -> (res: Option<LooseId>)
2599 requires
2600 old(self).inv(),
2601 old(self).cursors.dom().contains(id),
2602 ensures
2603 final(self).inv(),
2604 !(0 <= old(self).cursors[id].index < old(self).cursors[id].length()) ==> res is None
2605 && *final(self) == *old(self),
2606 0 <= old(self).cursors[id].index < old(self).cursors[id].length() ==> res is Some,
2607 {
2608 if !(0 <= self.cursors[id].index < self.cursors[id].length()) {
2609 Option::None
2612 } else {
2613 let ghost old_self = *self;
2614 let ghost old_regions = self.regions;
2615 let ghost n = self.cursors[id].index;
2616 let ghost old_list_id = self.cursors[id].list_own.list_id;
2617 let ghost popped_idx = self.cursors[id].list_own.slot_index_at(n);
2618 assert(self.cursors[id].list_own.relate_region(self.regions));
2619 assert(old_list_id != 0);
2621
2622 let tracked cur = self.cursors.tracked_remove(id);
2623 let tracked CursorOwner { list_own: mut owner, index: _ } = cur;
2624 let tracked frame_own = take_at_embedded(&mut self.regions, &mut owner, n);
2625 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(owner, n);
2626 self.cursors.tracked_insert(id, cur2);
2627 let ghost new_loose = fresh_loose_id(self.loose);
2628 lemma_fresh_loose_id_not_in_dom(self.loose);
2629 self.loose.tracked_insert(new_loose, frame_own);
2630
2631 assert(self.cursors =~= old_self.cursors.remove(id).insert(id, cur2));
2632 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
2633 assert(self.cursors[id].list_own.list_id == old_list_id);
2634 assert(self.cursors[id].list_own == owner);
2635 assert(frame_own.slot_index == popped_idx);
2636
2637 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
2639 &&& self.lists[i].inv()
2640 &&& self.lists[i].relate_region(self.regions)
2641 } by {
2642 assert(old_self.lists.dom().contains(i));
2643 assert(old_self.lists[i] == self.lists[i]);
2644 assert(old_self.lists[i].relate_region(old_regions));
2645 assert(old_self.cursors.dom().contains(id));
2646 assert(self.lists[i].list_id != old_list_id);
2647 assert(self.lists[i].relate_region(self.regions));
2648 };
2649
2650 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
2653 &&& self.loose[lid2].inv()
2654 &&& self.loose[lid2].global_inv(self.regions)
2655 &&& self.loose[lid2].frame_link_inv(self.regions)
2656 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2657 == 0
2658 } by {
2659 if lid2 != new_loose {
2660 assert(old_self.loose.dom().contains(lid2));
2661 assert(old_self.loose[lid2] == self.loose[lid2]);
2662 assert(old_self.loose[lid2].global_inv(old_regions));
2663 assert(old_self.loose[lid2].frame_link_inv(old_regions));
2664 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2665 == 0);
2666 }
2667 };
2668
2669 assert(self.lists.dom() =~= old_self.lists.dom());
2671 assert(self.cursors.dom() =~= old_self.cursors.dom());
2672 assert(self.lists.dom().disjoint(self.cursors.dom()));
2673
2674 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
2676 &&& self.cursors[cid].list_own.inv()
2677 &&& self.cursors[cid].wf_with_region(self.regions)
2678 } by {
2679 if cid == id {
2680 assert(self.cursors[id].list_own == owner);
2681 assert(self.cursors[id].index == n);
2682 assert(owner.list.len() == old_self.cursors[id].list_own.list.len() - 1);
2683 } else {
2684 assert(old_self.cursors.dom().contains(cid));
2685 assert(old_self.cursors[cid] == self.cursors[cid]);
2686 assert(old_self.cursors[cid].wf_with_region(old_regions));
2687 assert(self.cursors[cid].list_own.relate_region(old_regions));
2688 assert(self.cursors[cid].list_own.list_id != old_list_id);
2689 assert(self.cursors[cid].list_own.relate_region(self.regions));
2690 }
2691 };
2692
2693 assert forall|id2: ListId, cid: CursorId| #[trigger]
2695 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
2696 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
2697 && self.lists[id2].list_id != 0 implies false by {
2698 assert(old_self.lists.dom().contains(id2));
2699 assert(old_self.lists[id2] == self.lists[id2]);
2700 if cid == id {
2701 assert(self.cursors[id].list_own.list_id == old_list_id);
2702 assert(self.lists[id2].list_id != old_list_id);
2703 } else {
2704 assert(old_self.cursors.dom().contains(cid));
2705 assert(old_self.cursors[cid] == self.cursors[cid]);
2706 }
2707 };
2708
2709 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2711 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
2712 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
2713 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2714 assert(old_self.cursors.dom().contains(cid1));
2715 assert(old_self.cursors.dom().contains(cid2));
2716 assert(self.cursors[cid1].list_own.list_id
2717 == old_self.cursors[cid1].list_own.list_id);
2718 assert(self.cursors[cid2].list_own.list_id
2719 == old_self.cursors[cid2].list_own.list_id);
2720 };
2721
2722 assert forall|l1: LooseId, l2: LooseId|
2724 #![trigger self.loose.dom().contains(l1), self.loose.dom().contains(l2)]
2725 self.loose.dom().contains(l1) && self.loose.dom().contains(l2)
2726 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
2727 if l1 == new_loose && l2 != new_loose {
2728 assert(old_self.loose.dom().contains(l2));
2729 assert(self.loose[l2].slot_index != popped_idx);
2730 } else if l2 == new_loose && l1 != new_loose {
2731 assert(old_self.loose.dom().contains(l1));
2732 assert(self.loose[l1].slot_index != popped_idx);
2733 } else if l1 != new_loose && l2 != new_loose {
2734 assert(old_self.loose.dom().contains(l1));
2735 assert(old_self.loose.dom().contains(l2));
2736 }
2737 };
2738 Option::Some(new_loose)
2739 }
2740 }
2741}
2742
2743}