1use vstd::prelude::*;
58use vstd_extra::cast_ptr::Repr;
59use vstd_extra::ownership::*;
60use vstd_extra::set_extra::lemma_finite_int_set_has_unused;
61
62use crate::mm::Paddr;
63use crate::mm::frame::{
64 AnyFrameMeta, Link,
65 meta::{REF_COUNT_UNIQUE, REF_COUNT_UNUSED},
66};
67use crate::specs::arch::has_safe_slot;
68use crate::specs::mm::frame::linked_list::linked_list_owners::{
69 CursorOwner, LinkOwner, LinkedListOwner, MetaSlotSmall,
70};
71use crate::specs::mm::frame::mapping::frame_to_index;
72use crate::specs::mm::frame::meta_owners::PageUsage;
73use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
74use crate::specs::mm::frame::unique::UniqueFrameOwner;
75
76verus! {
77
78pub type ListId = int;
80
81pub type LooseId = int;
84
85pub type CursorId = ListId;
90
91pub open spec fn list_registry_ok<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
103 regions: MetaRegionOwners,
104 lo: LinkedListOwner<M>,
105) -> bool {
106 &&& forall|i: int|
107 #![trigger lo.slot_index_at(i)]
108 0 <= i < lo.list.len() ==> regions.slot_owners[lo.slot_index_at(
109 i,
110 )].inner_perms.in_list.value() == lo.list_id
111 &&& lo.list_id != 0 ==> forall|idx: usize|
112 #![trigger regions.slot_owners[idx]]
113 regions.slot_owners.contains_key(idx)
114 && regions.slot_owners[idx].inner_perms.in_list.value() == lo.list_id ==> exists|i: int|
115
116 0 <= i < lo.list.len() && lo.slot_index_at(i) == idx
117}
118
119pub tracked struct ListStore<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
128 pub regions: MetaRegionOwners,
129 pub lists: Map<ListId, LinkedListOwner<M>>,
130 pub loose: Map<LooseId, UniqueFrameOwner<Link<M>>>,
131 pub cursors: Map<CursorId, CursorOwner<M>>,
132}
133
134impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M> {
135 pub open spec fn inv(self) -> bool {
137 &&& self.regions.inv()
138 &&& forall|id: ListId| #[trigger]
141 self.lists.dom().contains(id) ==> {
142 &&& self.lists[id].inv()
143 &&& self.lists[id].relate_region(self.regions)
144 }
145 &&& forall|lid: LooseId| #[trigger]
152 self.loose.dom().contains(lid) ==> {
153 &&& self.loose[lid].inv()
154 &&& self.loose[lid].global_inv(self.regions)
155 &&& self.loose[lid].frame_link_inv(self.regions)
156 &&& self.regions.slot_owners[self.loose[lid].slot_index].inner_perms.in_list.value()
157 == 0
158 }
159 &&& forall|id1: ListId, id2: ListId|
166 #![trigger self.lists.dom().contains(id1), self.lists.dom().contains(id2)]
167 self.lists.dom().contains(id1) && self.lists.dom().contains(id2)
168 && self.lists[id1].list_id == self.lists[id2].list_id && self.lists[id1].list_id
169 != 0 ==> id1
170 == id2
171 &&& forall|lid1: LooseId, lid2: LooseId|
174 #![trigger self.loose.dom().contains(lid1), self.loose.dom().contains(lid2)]
175 self.loose.dom().contains(lid1) && self.loose.dom().contains(lid2)
176 && self.loose[lid1].slot_index == self.loose[lid2].slot_index ==> lid1
177 == lid2
178 &&& self.lists.dom().disjoint(
182 self.cursors.dom(),
183 )
184 &&& forall|cid: CursorId| #[trigger]
191 self.cursors.dom().contains(cid) ==> {
192 &&& self.cursors[cid].list_own.inv()
193 &&& self.cursors[cid].wf_with_region(self.regions)
194 }
195 &&& forall|id: ListId, cid: CursorId|
198 #![trigger self.lists.dom().contains(id), self.cursors.dom().contains(cid)]
199 self.lists.dom().contains(id) && self.cursors.dom().contains(cid)
200 && self.lists[id].list_id == self.cursors[cid].list_own.list_id
201 && self.lists[id].list_id != 0
202 ==> false
203 &&& forall|cid1: CursorId, cid2: CursorId|
205 #![trigger self.cursors.dom().contains(cid1), self.cursors.dom().contains(cid2)]
206 self.cursors.dom().contains(cid1) && self.cursors.dom().contains(cid2)
207 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
208 && self.cursors[cid1].list_own.list_id != 0 ==> cid1
209 == cid2
210 &&& forall|id: ListId| #[trigger]
214 self.lists.dom().contains(id) ==> list_registry_ok(
215 self.regions,
216 self.lists[id],
217 )
218 &&& forall|cid: CursorId| #[trigger]
220 self.cursors.dom().contains(cid) ==> list_registry_ok(
221 self.regions,
222 self.cursors[cid].list_own,
223 )
224 }
225}
226
227pub axiom fn axiom_empty_list_owner<M: AnyFrameMeta + Repr<MetaSlotSmall>>() -> (tracked res:
235 LinkedListOwner<M>)
236 ensures
237 res.list =~= Seq::<LinkOwner>::empty(),
238 res.list_id == 0,
239;
240
241pub open spec fn fresh_list_id<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
245 lists: Map<ListId, LinkedListOwner<M>>,
246 cursors: Map<CursorId, CursorOwner<M>>,
247) -> ListId {
248 choose|id: ListId| !lists.dom().contains(id) && !cursors.dom().contains(id)
249}
250
251pub proof fn lemma_fresh_list_id_not_in_dom<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
252 lists: Map<ListId, LinkedListOwner<M>>,
253 cursors: Map<CursorId, CursorOwner<M>>,
254)
255 ensures
256 !lists.dom().contains(fresh_list_id(lists, cursors)) && !cursors.dom().contains(
257 fresh_list_id(lists, cursors),
258 ),
259{
260 lemma_finite_int_set_has_unused(lists.dom() + cursors.dom());
261}
262
263pub axiom fn push_front_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
281 tracked regions: &mut MetaRegionOwners,
282 tracked owner: &mut LinkedListOwner<M>,
283 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
284 used_ids: Set<u64>,
285)
286 requires
287 old(regions).inv(),
288 old(owner).inv(),
289 old(owner).relate_region(*old(regions)),
290 old(frame_own).inv(),
291 old(frame_own).global_inv(*old(regions)),
292 old(frame_own).frame_link_inv(*old(regions)),
293 old(regions).slot_owners[old(frame_own).slot_index].inner_perms.in_list.value() == 0,
294 ensures
295 final(regions).inv(),
296 final(owner).inv(),
297 final(owner).relate_region(*final(regions)),
298 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
299 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
300 final(owner).list_id != 0,
301 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
302 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
303 final(frame_own).meta_own.in_list == final(owner).list_id,
304 final(regions).frame_obligations =~= old(regions).frame_obligations.remove(
305 old(frame_own).slot_index,
306 ),
307 forall|k: usize|
308 #![trigger final(regions).slots[k]]
309 #![trigger final(regions).slot_owners[k]]
310 k != old(frame_own).slot_index && (old(owner).list.len() > 0 ==> k != old(
311 owner,
312 ).slot_index_at(0)) ==> final(regions).slots[k] == old(regions).slots[k]
313 && final(regions).slot_owners[k] == old(regions).slot_owners[k],
314 forall|l: LinkedListOwner<M>|
315 #![trigger l.relate_region(*old(regions))]
316 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
317 ==> l.relate_region(*final(regions)),
318 list_registry_ok(*final(regions), *final(owner)),
322 forall|l: LinkedListOwner<M>|
327 #![trigger l.relate_region(*old(regions))]
328 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
329 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
330 forall|fo: UniqueFrameOwner<Link<M>>|
336 #![trigger fo.global_inv(*old(regions))]
337 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
338 regions,
339 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 && fo.slot_index != old(
340 frame_own,
341 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
342 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
343;
344
345pub open spec fn fresh_loose_id<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
347 m: Map<LooseId, UniqueFrameOwner<Link<M>>>,
348) -> LooseId {
349 choose|id: LooseId| !m.dom().contains(id)
350}
351
352pub proof fn lemma_fresh_loose_id_not_in_dom<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
353 m: Map<LooseId, UniqueFrameOwner<Link<M>>>,
354)
355 ensures
356 !m.dom().contains(fresh_loose_id(m)),
357{
358 lemma_finite_int_set_has_unused(m.dom());
359}
360
361pub axiom fn pop_front_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
376 tracked regions: &mut MetaRegionOwners,
377 tracked owner: &mut LinkedListOwner<M>,
378) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
379 requires
380 old(regions).inv(),
381 old(owner).inv(),
382 old(owner).relate_region(*old(regions)),
383 old(owner).list.len() > 0,
384 ensures
385 final(regions).inv(),
386 final(owner).inv(),
387 final(owner).relate_region(*final(regions)),
388 final(owner).list == old(owner).list.remove(0),
389 final(owner).list_id == old(owner).list_id,
390 frame_own.inv(),
392 frame_own.global_inv(*final(regions)),
393 frame_own.frame_link_inv(*final(regions)),
394 frame_own.slot_index == old(owner).slot_index_at(0),
395 final(regions).slot_owners[frame_own.slot_index].inner_perms.in_list.value() == 0,
396 final(regions).frame_obligations =~= old(regions).frame_obligations.insert(
398 old(owner).slot_index_at(0),
399 ),
400 forall|j: usize|
403 #![trigger final(regions).slots[j]]
404 #![trigger final(regions).slot_owners[j]]
405 j != old(owner).slot_index_at(0) && (old(owner).list.len() > 1 ==> j != old(
406 owner,
407 ).slot_index_at(1)) ==> final(regions).slots[j] == old(regions).slots[j]
408 && final(regions).slot_owners[j] == old(regions).slot_owners[j],
409 forall|l: LinkedListOwner<M>|
411 #![trigger l.relate_region(*old(regions))]
412 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
413 ==> l.relate_region(*final(regions)),
414 list_registry_ok(*final(regions), *final(owner)),
418 forall|l: LinkedListOwner<M>|
423 #![trigger l.relate_region(*old(regions))]
424 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
425 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
426 forall|fo: UniqueFrameOwner<Link<M>>|
429 #![trigger fo.global_inv(*old(regions))]
430 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
431 regions,
432 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
433 *final(regions),
434 ) && fo.frame_link_inv(*final(regions))
435 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0
436 && fo.slot_index != old(owner).slot_index_at(0),
437;
438
439pub axiom fn push_back_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
443 tracked regions: &mut MetaRegionOwners,
444 tracked owner: &mut LinkedListOwner<M>,
445 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
446 used_ids: Set<u64>,
447)
448 requires
449 old(regions).inv(),
450 old(owner).inv(),
451 old(owner).relate_region(*old(regions)),
452 old(frame_own).inv(),
453 old(frame_own).global_inv(*old(regions)),
454 old(frame_own).frame_link_inv(*old(regions)),
455 old(regions).slot_owners[old(frame_own).slot_index].inner_perms.in_list.value() == 0,
456 ensures
457 final(regions).inv(),
458 final(owner).inv(),
459 final(owner).relate_region(*final(regions)),
460 old(owner).list.len() > 0 ==> final(owner).list == old(owner).list.insert(
461 old(owner).list.len() - 1,
462 final(frame_own).meta_own,
463 ),
464 old(owner).list.len() == 0 ==> final(owner).list == old(owner).list.insert(
465 0,
466 final(frame_own).meta_own,
467 ),
468 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
469 final(owner).list_id != 0,
470 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
471 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
472 final(frame_own).meta_own.in_list == final(owner).list_id,
473 final(regions).frame_obligations =~= old(regions).frame_obligations.remove(
474 old(frame_own).slot_index,
475 ),
476 forall|k: usize|
477 #![trigger final(regions).slots[k]]
478 #![trigger final(regions).slot_owners[k]]
479 k != old(frame_own).slot_index && (old(owner).list.len() > 1 ==> k != old(
480 owner,
481 ).slot_index_at(old(owner).list.len() - 2)) && (old(owner).list.len() > 0 ==> k != old(
482 owner,
483 ).slot_index_at(old(owner).list.len() - 1)) ==> final(regions).slots[k] == old(
484 regions,
485 ).slots[k] && final(regions).slot_owners[k] == old(regions).slot_owners[k],
486 forall|l: LinkedListOwner<M>|
487 #![trigger l.relate_region(*old(regions))]
488 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
489 ==> l.relate_region(*final(regions)),
490 list_registry_ok(*final(regions), *final(owner)),
494 forall|l: LinkedListOwner<M>|
499 #![trigger l.relate_region(*old(regions))]
500 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
501 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
502 forall|fo: UniqueFrameOwner<Link<M>>|
503 #![trigger fo.global_inv(*old(regions))]
504 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
505 regions,
506 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 && fo.slot_index != old(
507 frame_own,
508 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
509 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
510;
511
512pub axiom fn pop_back_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
516 tracked regions: &mut MetaRegionOwners,
517 tracked owner: &mut LinkedListOwner<M>,
518) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
519 requires
520 old(regions).inv(),
521 old(owner).inv(),
522 old(owner).relate_region(*old(regions)),
523 old(owner).list.len() > 0,
524 ensures
525 final(regions).inv(),
526 final(owner).inv(),
527 final(owner).relate_region(*final(regions)),
528 final(owner).list == old(owner).list.remove(old(owner).list.len() - 1),
529 final(owner).list_id == old(owner).list_id,
530 frame_own.inv(),
531 frame_own.global_inv(*final(regions)),
532 frame_own.frame_link_inv(*final(regions)),
533 frame_own.slot_index == old(owner).slot_index_at(old(owner).list.len() - 1),
534 final(regions).slot_owners[frame_own.slot_index].inner_perms.in_list.value() == 0,
535 final(regions).frame_obligations =~= old(regions).frame_obligations.insert(
536 old(owner).slot_index_at(old(owner).list.len() - 1),
537 ),
538 forall|j: usize|
539 #![trigger final(regions).slots[j]]
540 #![trigger final(regions).slot_owners[j]]
541 j != old(owner).slot_index_at(old(owner).list.len() - 1) && (old(owner).list.len() > 1
542 ==> j != old(owner).slot_index_at(old(owner).list.len() - 2))
543 ==> final(regions).slots[j] == old(regions).slots[j]
544 && final(regions).slot_owners[j] == old(regions).slot_owners[j],
545 forall|l: LinkedListOwner<M>|
546 #![trigger l.relate_region(*old(regions))]
547 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
548 ==> l.relate_region(*final(regions)),
549 list_registry_ok(*final(regions), *final(owner)),
553 forall|l: LinkedListOwner<M>|
558 #![trigger l.relate_region(*old(regions))]
559 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
560 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
561 forall|fo: UniqueFrameOwner<Link<M>>|
562 #![trigger fo.global_inv(*old(regions))]
563 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
564 regions,
565 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
566 *final(regions),
567 ) && fo.frame_link_inv(*final(regions))
568 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0
569 && fo.slot_index != old(owner).slot_index_at(old(owner).list.len() - 1),
570;
571
572pub axiom fn insert_before_at_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
578 tracked regions: &mut MetaRegionOwners,
579 tracked owner: &mut LinkedListOwner<M>,
580 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
581 n: int,
582 used_ids: Set<u64>,
583)
584 requires
585 old(regions).inv(),
586 old(owner).inv(),
587 old(owner).relate_region(*old(regions)),
588 old(frame_own).inv(),
589 old(frame_own).global_inv(*old(regions)),
590 old(frame_own).frame_link_inv(*old(regions)),
591 old(regions).slot_owners[old(frame_own).slot_index].inner_perms.in_list.value() == 0,
592 0 <= n <= old(owner).list.len(),
593 ensures
594 final(regions).inv(),
595 final(owner).inv(),
596 final(owner).relate_region(*final(regions)),
597 final(owner).list == old(owner).list.insert(n, final(frame_own).meta_own),
598 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
599 final(owner).list_id != 0,
600 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
601 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
602 final(frame_own).meta_own.in_list == final(owner).list_id,
603 final(regions).frame_obligations =~= old(regions).frame_obligations.remove(
604 old(frame_own).slot_index,
605 ),
606 forall|k: usize|
607 #![trigger final(regions).slots[k]]
608 #![trigger final(regions).slot_owners[k]]
609 k != old(frame_own).slot_index && (n > 0 ==> k != old(owner).slot_index_at(n - 1)) && (n
610 < old(owner).list.len() ==> k != old(owner).slot_index_at(n))
611 ==> final(regions).slots[k] == old(regions).slots[k]
612 && final(regions).slot_owners[k] == old(regions).slot_owners[k],
613 forall|l: LinkedListOwner<M>|
614 #![trigger l.relate_region(*old(regions))]
615 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
616 ==> l.relate_region(*final(regions)),
617 list_registry_ok(*final(regions), *final(owner)),
621 forall|l: LinkedListOwner<M>|
626 #![trigger l.relate_region(*old(regions))]
627 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
628 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
629 forall|fo: UniqueFrameOwner<Link<M>>|
630 #![trigger fo.global_inv(*old(regions))]
631 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
632 regions,
633 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 && fo.slot_index != old(
634 frame_own,
635 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
636 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
637;
638
639pub axiom fn take_at_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
645 tracked regions: &mut MetaRegionOwners,
646 tracked owner: &mut LinkedListOwner<M>,
647 n: int,
648) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
649 requires
650 old(regions).inv(),
651 old(owner).inv(),
652 old(owner).relate_region(*old(regions)),
653 0 <= n < old(owner).list.len(),
654 ensures
655 final(regions).inv(),
656 final(owner).inv(),
657 final(owner).relate_region(*final(regions)),
658 final(owner).list == old(owner).list.remove(n),
659 final(owner).list_id == old(owner).list_id,
660 frame_own.inv(),
661 frame_own.global_inv(*final(regions)),
662 frame_own.frame_link_inv(*final(regions)),
663 frame_own.slot_index == old(owner).slot_index_at(n),
664 final(regions).slot_owners[frame_own.slot_index].inner_perms.in_list.value() == 0,
665 final(regions).frame_obligations =~= old(regions).frame_obligations.insert(
666 old(owner).slot_index_at(n),
667 ),
668 forall|j: usize|
669 #![trigger final(regions).slots[j]]
670 #![trigger final(regions).slot_owners[j]]
671 j != old(owner).slot_index_at(n) && (n > 0 ==> j != old(owner).slot_index_at(n - 1))
672 && (n < old(owner).list.len() - 1 ==> j != old(owner).slot_index_at(n + 1))
673 ==> final(regions).slots[j] == old(regions).slots[j]
674 && final(regions).slot_owners[j] == old(regions).slot_owners[j],
675 forall|l: LinkedListOwner<M>|
676 #![trigger l.relate_region(*old(regions))]
677 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
678 ==> l.relate_region(*final(regions)),
679 list_registry_ok(*final(regions), *final(owner)),
683 forall|l: LinkedListOwner<M>|
688 #![trigger l.relate_region(*old(regions))]
689 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
690 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
691 forall|fo: UniqueFrameOwner<Link<M>>|
692 #![trigger fo.global_inv(*old(regions))]
693 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
694 regions,
695 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
696 *final(regions),
697 ) && fo.frame_link_inv(*final(regions))
698 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0
699 && fo.slot_index != old(owner).slot_index_at(n),
700;
701
702pub axiom fn list_drop_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
719 tracked regions: &mut MetaRegionOwners,
720 tracked owner: LinkedListOwner<M>,
721)
722 requires
723 old(regions).inv(),
724 owner.inv(),
725 owner.relate_region(*old(regions)),
726 forall|i: int|
727 #![trigger owner.slot_index_at(i)]
728 0 <= i < owner.list.len() ==> old(regions).frame_obligations.count(
729 owner.slot_index_at(i),
730 ) == 0,
731 forall|i: int|
739 #![trigger owner.slot_index_at(i)]
740 0 <= i < owner.list.len() ==> old(regions).slot_owners[owner.slot_index_at(
741 i,
742 )].paths_in_pt.is_empty(),
743 ensures
744 final(regions).inv(),
745 final(regions).slots.dom() =~= old(regions).slots.dom(),
746 owner.list.len() == 0 ==> *final(regions) == *old(regions),
748 forall|i: int|
750 #![trigger owner.slot_index_at(i)]
751 0 <= i < owner.list.len() ==> {
752 let idx = owner.slot_index_at(i);
753 &&& final(regions).slot_owners[idx].inner_perms.ref_count.value()
754 == REF_COUNT_UNUSED
755 &&& final(regions).slot_owners[idx].inner_perms.in_list.value() == 0
756 },
757 forall|idx: usize|
759 #![trigger final(regions).slot_owners[idx]]
760 (forall|i: int| 0 <= i < owner.list.len() ==> idx != owner.slot_index_at(i))
761 ==> final(regions).slot_owners[idx] == old(regions).slot_owners[idx]
762 && final(regions).slots[idx] == old(regions).slots[idx]
763 && final(regions).frame_obligations.count(idx) == old(
764 regions,
765 ).frame_obligations.count(idx),
766 forall|l: LinkedListOwner<M>|
768 #![trigger l.relate_region(*old(regions))]
769 l.inv() && l.relate_region(*old(regions)) && l.list_id != owner.list_id
770 ==> l.relate_region(*final(regions)),
771 forall|l: LinkedListOwner<M>|
772 #![trigger l.relate_region(*old(regions))]
773 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
774 && l.list_id != owner.list_id ==> list_registry_ok(*final(regions), l),
775 forall|fo: UniqueFrameOwner<Link<M>>|
778 #![trigger fo.global_inv(*old(regions))]
779 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
780 regions,
781 ).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0 ==> fo.global_inv(
782 *final(regions),
783 ) && fo.frame_link_inv(*final(regions))
784 && final(regions).slot_owners[fo.slot_index].inner_perms.in_list.value() == 0,
785;
786
787impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M> {
791 pub proof fn step_size(tracked &self, id: ListId) -> (res: nat)
794 requires
795 self.inv(),
796 self.lists.dom().contains(id),
797 ensures
798 res == self.lists[id].list.len(),
799 {
800 self.lists[id].list.len()
801 }
802
803 pub proof fn step_is_empty(tracked &self, id: ListId) -> (res: bool)
805 requires
806 self.inv(),
807 self.lists.dom().contains(id),
808 ensures
809 res <==> self.lists[id].list.len() == 0,
810 {
811 self.lists[id].list.len() == 0
812 }
813
814 pub proof fn step_contains(tracked &self, id: ListId, frame: Paddr) -> (res: bool)
824 requires
825 self.inv(),
826 self.lists.dom().contains(id),
827 ensures
828 res <==> (has_safe_slot(frame) && exists|i: int|
829 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i)
830 == frame_to_index(frame)),
831 {
832 let idx = frame_to_index(frame);
833 if has_safe_slot(frame) {
834 self.regions.inv_implies_correct_addr(frame);
836 assert(self.regions.slot_owners.contains_key(idx));
837 if self.lists[id].list_id != 0 {
838 assert(list_registry_ok(self.regions, self.lists[id]));
840 let res = self.regions.slot_owners[idx].inner_perms.in_list.value()
841 == self.lists[id].list_id;
842 if res {
843 assert(exists|i: int|
845 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i)
846 == idx);
847 } else {
848 assert forall|i: int|
851 0 <= i < self.lists[id].list.len() implies self.lists[id].slot_index_at(i)
852 != idx by {
853 assert(self.regions.slot_owners[self.lists[id].slot_index_at(
854 i,
855 )].inner_perms.in_list.value() == self.lists[id].list_id);
856 };
857 }
858 res
859 } else {
860 assert(self.lists[id].list.len() == 0);
863 false
864 }
865 } else {
866 false
869 }
870 }
871
872 pub proof fn step_list_new(tracked &mut self) -> (res: ListId)
876 requires
877 old(self).inv(),
878 ensures
879 final(self).inv(),
880 final(self).regions == old(self).regions,
881 final(self).loose == old(self).loose,
882 !old(self).lists.dom().contains(res),
883 final(self).lists == old(self).lists.insert(res, final(self).lists[res]),
884 final(self).lists[res].list.len() == 0,
885 {
886 let ghost old_self = *self;
887 let ghost id = fresh_list_id(self.lists, self.cursors);
888 lemma_fresh_list_id_not_in_dom(self.lists, self.cursors);
889 let tracked empty = axiom_empty_list_owner::<M>();
890 self.lists.tracked_insert(id, empty);
891 assert(self.lists[id].list.len() == 0);
892 assert(self.lists[id].relate_region(self.regions));
897 assert(self.cursors == old_self.cursors);
901 assert(self.lists.dom().disjoint(self.cursors.dom()));
902 assert(self.lists[id].list_id == 0);
903 id
904 }
905
906 pub proof fn step_list_drop(tracked &mut self, id: ListId)
917 requires
918 old(self).inv(),
919 old(self).lists.dom().contains(id),
920 forall|i: int|
921 0 <= i < old(self).lists[id].list.len() ==> old(
922 self,
923 ).regions.frame_obligations.count(#[trigger] old(self).lists[id].slot_index_at(i))
924 == 0,
925 ensures
926 final(self).inv(),
927 !final(self).lists.dom().contains(id),
928 final(self).loose == old(self).loose,
929 final(self).cursors == old(self).cursors,
930 {
931 let ghost old_self = *self;
932 let ghost old_regions = self.regions;
933 let ghost dropped_id = self.lists[id].list_id;
934 let ghost is_empty = self.lists[id].list.len() == 0;
935 assert(self.lists[id].relate_region(self.regions));
936
937 assert forall|i: int|
943 #![trigger self.lists[id].slot_index_at(i)]
944 0 <= i
945 < self.lists[id].list.len() implies self.regions.slot_owners[self.lists[id].slot_index_at(
946 i)].paths_in_pt.is_empty() by {
947 let idx = self.lists[id].slot_index_at(i);
948 let _ = self.lists[id].list[i];
951 self.lists[id].relate_region_at_facts(self.regions, i);
952 assert(self.regions.slot_owners.contains_key(idx));
953 assert(self.regions.slot_owners[idx].inner_perms.ref_count.value() == REF_COUNT_UNIQUE);
954 assert(self.regions.slot_owners[idx].usage == PageUsage::Frame);
955 };
956
957 let tracked owner = self.lists.tracked_remove(id);
958 list_drop_embedded(&mut self.regions, owner);
959 assert(self.lists =~= old_self.lists.remove(id));
960 if is_empty {
961 assert(self.regions == old_regions);
962 }
963 if !is_empty {
968 assert(dropped_id != 0);
969 }
970 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
973 &&& self.lists[i].inv()
974 &&& self.lists[i].relate_region(self.regions)
975 } by {
976 assert(i != id);
977 assert(old_self.lists.dom().contains(i));
978 assert(old_self.lists[i] == self.lists[i]);
979 assert(old_self.lists[i].relate_region(old_regions));
980 if !is_empty {
981 assert(self.lists[i].list_id != dropped_id);
982 }
983 };
984
985 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
987 &&& self.loose[lid2].inv()
988 &&& self.loose[lid2].global_inv(self.regions)
989 &&& self.loose[lid2].frame_link_inv(self.regions)
990 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
991 == 0
992 } by {
993 assert(old_self.loose.dom().contains(lid2));
994 assert(old_self.loose[lid2].global_inv(old_regions));
995 assert(old_self.loose[lid2].frame_link_inv(old_regions));
996 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
997 == 0);
998 };
999
1000 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1002 &&& self.cursors[cid].list_own.inv()
1003 &&& self.cursors[cid].wf_with_region(self.regions)
1004 } by {
1005 assert(old_self.cursors.dom().contains(cid));
1006 assert(old_self.cursors[cid].wf_with_region(old_regions));
1007 assert(self.cursors[cid].list_own.relate_region(old_regions));
1008 if !is_empty {
1009 assert(self.cursors[cid].list_own.list_id != dropped_id);
1010 }
1011 };
1012
1013 assert forall|i1: ListId, i2: ListId| #[trigger]
1015 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1016 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1017 != 0 implies i1 == i2 by {
1018 assert(old_self.lists.dom().contains(i1));
1019 assert(old_self.lists.dom().contains(i2));
1020 };
1021
1022 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1024 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1025 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1026 assert(old_self.loose.dom().contains(l1));
1027 assert(old_self.loose.dom().contains(l2));
1028 };
1029
1030 assert(self.lists.dom().disjoint(self.cursors.dom()));
1032 assert forall|id2: ListId, cid: CursorId| #[trigger]
1033 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1034 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1035 && self.lists[id2].list_id != 0 implies false by {
1036 assert(old_self.lists.dom().contains(id2));
1037 assert(old_self.cursors.dom().contains(cid));
1038 };
1039 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1040 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1041 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1042 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1043 assert(old_self.cursors.dom().contains(cid1));
1044 assert(old_self.cursors.dom().contains(cid2));
1045 };
1046
1047 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies list_registry_ok(
1049 self.regions,
1050 self.lists[i],
1051 ) by {
1052 assert(old_self.lists.dom().contains(i));
1053 assert(old_self.lists[i] == self.lists[i]);
1054 assert(old_self.lists[i].relate_region(old_regions));
1055 if !is_empty {
1056 assert(self.lists[i].list_id != dropped_id);
1057 }
1058 };
1059 assert forall|cid: CursorId| #[trigger]
1060 self.cursors.dom().contains(cid) implies list_registry_ok(
1061 self.regions,
1062 self.cursors[cid].list_own,
1063 ) by {
1064 assert(old_self.cursors.dom().contains(cid));
1065 assert(old_self.cursors[cid].list_own.relate_region(old_regions));
1066 if !is_empty {
1067 assert(self.cursors[cid].list_own.list_id != dropped_id);
1068 }
1069 };
1070 }
1071
1072 pub proof fn step_push_front(tracked &mut self, id: ListId, lid: LooseId)
1076 requires
1077 old(self).inv(),
1078 old(self).lists.dom().contains(id),
1079 old(self).loose.dom().contains(lid),
1080 ensures
1081 final(self).inv(),
1082 {
1083 let ghost old_self = *self;
1084 let ghost old_regions = self.regions;
1085 let ghost fidx = self.loose[lid].slot_index;
1086 let ghost used = Set::<u64>::full().unwrap().filter(
1088 |x: u64|
1089 (exists|i: ListId| #[trigger]
1090 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
1091 || (exists|cid: CursorId| #[trigger]
1092 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
1093 == x),
1094 );
1095 assert(self.lists[id].relate_region(self.regions));
1097 assert(self.loose[lid].global_inv(self.regions));
1098 assert(self.loose[lid].frame_link_inv(self.regions));
1099 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
1100
1101 let tracked mut owner = self.lists.tracked_remove(id);
1102 let tracked mut frame_own = self.loose.tracked_remove(lid);
1103 push_front_embedded(&mut self.regions, &mut owner, &mut frame_own, used);
1104 self.lists.tracked_insert(id, owner);
1105 assert(self.loose =~= old_self.loose.remove(lid));
1106 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1107 let ghost new_id = self.lists[id].list_id;
1108
1109 assert forall|i: ListId| #[trigger]
1113 self.lists.dom().contains(i) && i != id && self.lists[i].list_id
1114 != 0 implies self.lists[i].list_id != new_id by {
1115 assert(old_self.lists.dom().contains(i));
1116 assert(old_self.lists[i] == self.lists[i]);
1117 if old_self.lists[id].list_id != 0 {
1118 assert(new_id == old_self.lists[id].list_id);
1120 } else {
1121 assert(used.contains(self.lists[i].list_id));
1122 }
1123 };
1124
1125 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1127 &&& self.lists[i].inv()
1128 &&& self.lists[i].relate_region(self.regions)
1129 } by {
1130 if i != id {
1131 assert(old_self.lists.dom().contains(i));
1132 assert(old_self.lists[i] == self.lists[i]);
1133 assert(old_self.lists[i].relate_region(old_regions));
1134 if self.lists[i].list.len() > 0 {
1135 assert(self.lists[i].list_id != new_id);
1136 }
1137 }
1138 };
1139
1140 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1143 &&& self.loose[lid2].inv()
1144 &&& self.loose[lid2].global_inv(self.regions)
1145 &&& self.loose[lid2].frame_link_inv(self.regions)
1146 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1147 == 0
1148 } by {
1149 assert(lid2 != lid);
1150 assert(old_self.loose.dom().contains(lid2));
1151 assert(old_self.loose[lid2] == self.loose[lid2]);
1152 assert(old_self.loose[lid2].global_inv(old_regions));
1153 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1154 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1155 == 0);
1156 assert(self.loose[lid2].slot_index != fidx);
1157 };
1158
1159 assert forall|i1: ListId, i2: ListId| #[trigger]
1161 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1162 && self.lists[i1].list.len() > 0 && self.lists[i2].list.len() > 0
1163 && self.lists[i1].list_id == self.lists[i2].list_id implies i1 == i2 by {
1164 if i1 != id && i2 != id {
1165 assert(old_self.lists[i1] == self.lists[i1]);
1166 assert(old_self.lists[i2] == self.lists[i2]);
1167 } else if i1 == id && i2 != id {
1168 assert(self.lists[i2].list_id != new_id);
1169 } else if i2 == id && i1 != id {
1170 assert(self.lists[i1].list_id != new_id);
1171 }
1172 };
1173
1174 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1176 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1177 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1178 assert(old_self.loose.dom().contains(l1));
1179 assert(old_self.loose.dom().contains(l2));
1180 };
1181
1182 assert(self.cursors == old_self.cursors);
1190 assert(self.lists.dom() =~= old_self.lists.dom());
1191 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1192 &&& self.cursors[cid].list_own.inv()
1193 &&& self.cursors[cid].wf_with_region(self.regions)
1194 } by {
1195 assert(old_self.cursors.dom().contains(cid));
1196 assert(old_self.cursors[cid].wf_with_region(old_regions));
1197 assert(self.cursors[cid].list_own.relate_region(old_regions));
1198 if old_self.lists[id].list_id != 0 {
1199 assert(new_id == old_self.lists[id].list_id);
1200 } else {
1201 assert(used.contains(self.cursors[cid].list_own.list_id));
1202 }
1203 assert(self.cursors[cid].list_own.list_id != new_id);
1204 assert(self.cursors[cid].list_own.relate_region(self.regions));
1205 };
1206 assert forall|id2: ListId, cid: CursorId| #[trigger]
1207 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1208 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1209 && self.lists[id2].list_id != 0 implies false by {
1210 assert(old_self.cursors.dom().contains(cid));
1211 if id2 == id {
1212 assert(self.lists[id].list_id == new_id);
1213 if old_self.lists[id].list_id != 0 {
1214 assert(new_id == old_self.lists[id].list_id);
1215 } else {
1216 assert(used.contains(self.cursors[cid].list_own.list_id));
1217 }
1218 } else {
1219 assert(old_self.lists.dom().contains(id2));
1220 assert(old_self.lists[id2] == self.lists[id2]);
1221 }
1222 };
1223 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1224 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1225 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1226 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1227 assert(old_self.cursors.dom().contains(cid1));
1228 assert(old_self.cursors.dom().contains(cid2));
1229 };
1230 }
1231
1232 pub proof fn step_pop_front(tracked &mut self, id: ListId) -> (res: Option<LooseId>)
1236 requires
1237 old(self).inv(),
1238 old(self).lists.dom().contains(id),
1239 ensures
1240 final(self).inv(),
1241 old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),
1242 old(self).lists[id].list.len() > 0 ==> res is Some,
1243 {
1244 if self.lists[id].list.len() == 0 {
1245 Option::None
1248 } else {
1249 let ghost old_self = *self;
1250 let ghost old_regions = self.regions;
1251 let ghost popped_idx = self.lists[id].slot_index_at(0);
1252 let ghost old_list_id = self.lists[id].list_id;
1253 assert(self.lists[id].relate_region(self.regions));
1255
1256 let tracked mut owner = self.lists.tracked_remove(id);
1257 let tracked frame_own = pop_front_embedded(&mut self.regions, &mut owner);
1258 self.lists.tracked_insert(id, owner);
1259 let ghost new_loose = fresh_loose_id(self.loose);
1260 lemma_fresh_loose_id_not_in_dom(self.loose);
1261 self.loose.tracked_insert(new_loose, frame_own);
1262
1263 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1264 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
1265 assert(self.lists[id].list_id == old_list_id);
1266 assert(frame_own.slot_index == popped_idx);
1267
1268 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1270 &&& self.lists[i].inv()
1271 &&& self.lists[i].relate_region(self.regions)
1272 } by {
1273 if i != id {
1274 assert(old_self.lists.dom().contains(i));
1275 assert(old_self.lists[i] == self.lists[i]);
1276 assert(old_self.lists[i].relate_region(old_regions));
1277 if self.lists[i].list.len() > 0 {
1278 assert(self.lists[i].list_id != old_list_id);
1281 }
1282 }
1283 };
1284
1285 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1287 &&& self.loose[lid2].inv()
1288 &&& self.loose[lid2].global_inv(self.regions)
1289 &&& self.loose[lid2].frame_link_inv(self.regions)
1290 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1291 == 0
1292 } by {
1293 if lid2 != new_loose {
1294 assert(old_self.loose.dom().contains(lid2));
1295 assert(old_self.loose[lid2] == self.loose[lid2]);
1296 assert(old_self.loose[lid2].global_inv(old_regions));
1297 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1298 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1299 == 0);
1300 }
1301 };
1302
1303 assert forall|i1: ListId, i2: ListId| #[trigger]
1305 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1306 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1307 != 0 implies i1 == i2 by {
1308 assert(old_self.lists.dom().contains(i1));
1309 assert(old_self.lists.dom().contains(i2));
1310 assert(self.lists[i1].list_id == old_self.lists[i1].list_id);
1311 assert(self.lists[i2].list_id == old_self.lists[i2].list_id);
1312 };
1313
1314 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1316 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1317 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1318 if l1 == new_loose && l2 != new_loose {
1319 assert(old_self.loose.dom().contains(l2));
1320 assert(self.loose[l2].slot_index != popped_idx);
1321 } else if l2 == new_loose && l1 != new_loose {
1322 assert(old_self.loose.dom().contains(l1));
1323 assert(self.loose[l1].slot_index != popped_idx);
1324 } else if l1 != new_loose && l2 != new_loose {
1325 assert(old_self.loose.dom().contains(l1));
1326 assert(old_self.loose.dom().contains(l2));
1327 }
1328 };
1329
1330 assert(self.cursors == old_self.cursors);
1335 assert(self.lists.dom() =~= old_self.lists.dom());
1336 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1337 &&& self.cursors[cid].list_own.inv()
1338 &&& self.cursors[cid].wf_with_region(self.regions)
1339 } by {
1340 assert(old_self.cursors.dom().contains(cid));
1341 assert(old_self.cursors[cid].wf_with_region(old_regions));
1342 assert(self.cursors[cid].list_own.relate_region(old_regions));
1343 assert(old_self.lists.dom().contains(id));
1344 assert(old_self.lists[id].list_id == old_list_id);
1345 assert(self.cursors[cid].list_own.list_id != old_list_id);
1346 assert(self.cursors[cid].list_own.relate_region(self.regions));
1347 };
1348 assert forall|id2: ListId, cid: CursorId| #[trigger]
1349 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1350 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1351 && self.lists[id2].list_id != 0 implies false by {
1352 assert(old_self.cursors.dom().contains(cid));
1353 assert(old_self.lists.dom().contains(id2));
1354 assert(old_self.lists[id2].list_id == self.lists[id2].list_id);
1355 };
1356 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1357 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1358 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1359 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1360 assert(old_self.cursors.dom().contains(cid1));
1361 assert(old_self.cursors.dom().contains(cid2));
1362 };
1363 Option::Some(new_loose)
1364 }
1365 }
1366
1367 pub proof fn step_push_back(tracked &mut self, id: ListId, lid: LooseId)
1371 requires
1372 old(self).inv(),
1373 old(self).lists.dom().contains(id),
1374 old(self).loose.dom().contains(lid),
1375 ensures
1376 final(self).inv(),
1377 {
1378 let ghost old_self = *self;
1379 let ghost old_regions = self.regions;
1380 let ghost fidx = self.loose[lid].slot_index;
1381 let ghost used = Set::<u64>::full().unwrap().filter(
1382 |x: u64|
1383 (exists|i: ListId| #[trigger]
1384 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
1385 || (exists|cid: CursorId| #[trigger]
1386 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
1387 == x),
1388 );
1389 assert(self.lists[id].relate_region(self.regions));
1390 assert(self.loose[lid].global_inv(self.regions));
1391 assert(self.loose[lid].frame_link_inv(self.regions));
1392 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
1393
1394 let tracked mut owner = self.lists.tracked_remove(id);
1395 let tracked mut frame_own = self.loose.tracked_remove(lid);
1396 push_back_embedded(&mut self.regions, &mut owner, &mut frame_own, used);
1397 self.lists.tracked_insert(id, owner);
1398 assert(self.loose =~= old_self.loose.remove(lid));
1399 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1400 let ghost new_id = self.lists[id].list_id;
1401
1402 assert forall|i: ListId| #[trigger]
1403 self.lists.dom().contains(i) && i != id && self.lists[i].list_id
1404 != 0 implies self.lists[i].list_id != new_id by {
1405 assert(old_self.lists.dom().contains(i));
1406 assert(old_self.lists[i] == self.lists[i]);
1407 if old_self.lists[id].list_id != 0 {
1408 assert(new_id == old_self.lists[id].list_id);
1409 } else {
1410 assert(used.contains(self.lists[i].list_id));
1411 }
1412 };
1413
1414 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1415 &&& self.lists[i].inv()
1416 &&& self.lists[i].relate_region(self.regions)
1417 } by {
1418 if i != id {
1419 assert(old_self.lists.dom().contains(i));
1420 assert(old_self.lists[i] == self.lists[i]);
1421 assert(old_self.lists[i].relate_region(old_regions));
1422 if self.lists[i].list.len() > 0 {
1423 assert(self.lists[i].list_id != new_id);
1424 }
1425 }
1426 };
1427
1428 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1429 &&& self.loose[lid2].inv()
1430 &&& self.loose[lid2].global_inv(self.regions)
1431 &&& self.loose[lid2].frame_link_inv(self.regions)
1432 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1433 == 0
1434 } by {
1435 assert(lid2 != lid);
1436 assert(old_self.loose.dom().contains(lid2));
1437 assert(old_self.loose[lid2] == self.loose[lid2]);
1438 assert(old_self.loose[lid2].global_inv(old_regions));
1439 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1440 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1441 == 0);
1442 assert(self.loose[lid2].slot_index != fidx);
1443 };
1444
1445 assert forall|i1: ListId, i2: ListId| #[trigger]
1446 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1447 && self.lists[i1].list.len() > 0 && self.lists[i2].list.len() > 0
1448 && self.lists[i1].list_id == self.lists[i2].list_id implies i1 == i2 by {
1449 if i1 != id && i2 != id {
1450 assert(old_self.lists[i1] == self.lists[i1]);
1451 assert(old_self.lists[i2] == self.lists[i2]);
1452 } else if i1 == id && i2 != id {
1453 assert(self.lists[i2].list_id != new_id);
1454 } else if i2 == id && i1 != id {
1455 assert(self.lists[i1].list_id != new_id);
1456 }
1457 };
1458
1459 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1460 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1461 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1462 assert(old_self.loose.dom().contains(l1));
1463 assert(old_self.loose.dom().contains(l2));
1464 };
1465
1466 assert(self.cursors == old_self.cursors);
1474 assert(self.lists.dom() =~= old_self.lists.dom());
1475 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1476 &&& self.cursors[cid].list_own.inv()
1477 &&& self.cursors[cid].wf_with_region(self.regions)
1478 } by {
1479 assert(old_self.cursors.dom().contains(cid));
1480 assert(old_self.cursors[cid].wf_with_region(old_regions));
1481 assert(self.cursors[cid].list_own.relate_region(old_regions));
1482 if old_self.lists[id].list_id != 0 {
1483 assert(new_id == old_self.lists[id].list_id);
1484 } else {
1485 assert(used.contains(self.cursors[cid].list_own.list_id));
1486 }
1487 assert(self.cursors[cid].list_own.list_id != new_id);
1488 assert(self.cursors[cid].list_own.relate_region(self.regions));
1489 };
1490 assert forall|id2: ListId, cid: CursorId| #[trigger]
1491 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1492 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1493 && self.lists[id2].list_id != 0 implies false by {
1494 assert(old_self.cursors.dom().contains(cid));
1495 if id2 == id {
1496 assert(self.lists[id].list_id == new_id);
1497 if old_self.lists[id].list_id != 0 {
1498 assert(new_id == old_self.lists[id].list_id);
1499 } else {
1500 assert(used.contains(self.cursors[cid].list_own.list_id));
1501 }
1502 } else {
1503 assert(old_self.lists.dom().contains(id2));
1504 assert(old_self.lists[id2] == self.lists[id2]);
1505 }
1506 };
1507 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1508 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1509 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1510 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1511 assert(old_self.cursors.dom().contains(cid1));
1512 assert(old_self.cursors.dom().contains(cid2));
1513 };
1514 }
1515
1516 pub proof fn step_pop_back(tracked &mut self, id: ListId) -> (res: Option<LooseId>)
1520 requires
1521 old(self).inv(),
1522 old(self).lists.dom().contains(id),
1523 ensures
1524 final(self).inv(),
1525 old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),
1526 old(self).lists[id].list.len() > 0 ==> res is Some,
1527 {
1528 if self.lists[id].list.len() == 0 {
1529 Option::None
1532 } else {
1533 let ghost old_self = *self;
1534 let ghost old_regions = self.regions;
1535 let ghost popped_idx = self.lists[id].slot_index_at(self.lists[id].list.len() - 1);
1536 let ghost old_list_id = self.lists[id].list_id;
1537 assert(self.lists[id].relate_region(self.regions));
1538
1539 let tracked mut owner = self.lists.tracked_remove(id);
1540 let tracked frame_own = pop_back_embedded(&mut self.regions, &mut owner);
1541 self.lists.tracked_insert(id, owner);
1542 let ghost new_loose = fresh_loose_id(self.loose);
1543 lemma_fresh_loose_id_not_in_dom(self.loose);
1544 self.loose.tracked_insert(new_loose, frame_own);
1545
1546 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1547 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
1548 assert(self.lists[id].list_id == old_list_id);
1549 assert(frame_own.slot_index == popped_idx);
1550
1551 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1552 &&& self.lists[i].inv()
1553 &&& self.lists[i].relate_region(self.regions)
1554 } by {
1555 if i != id {
1556 assert(old_self.lists.dom().contains(i));
1557 assert(old_self.lists[i] == self.lists[i]);
1558 assert(old_self.lists[i].relate_region(old_regions));
1559 if self.lists[i].list.len() > 0 {
1560 assert(self.lists[i].list_id != old_list_id);
1561 }
1562 }
1563 };
1564
1565 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1566 &&& self.loose[lid2].inv()
1567 &&& self.loose[lid2].global_inv(self.regions)
1568 &&& self.loose[lid2].frame_link_inv(self.regions)
1569 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1570 == 0
1571 } by {
1572 if lid2 != new_loose {
1573 assert(old_self.loose.dom().contains(lid2));
1574 assert(old_self.loose[lid2] == self.loose[lid2]);
1575 assert(old_self.loose[lid2].global_inv(old_regions));
1576 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1577 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1578 == 0);
1579 }
1580 };
1581
1582 assert forall|i1: ListId, i2: ListId| #[trigger]
1583 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1584 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1585 != 0 implies i1 == i2 by {
1586 assert(old_self.lists.dom().contains(i1));
1587 assert(old_self.lists.dom().contains(i2));
1588 assert(self.lists[i1].list_id == old_self.lists[i1].list_id);
1589 assert(self.lists[i2].list_id == old_self.lists[i2].list_id);
1590 };
1591
1592 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1593 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1594 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1595 if l1 == new_loose && l2 != new_loose {
1596 assert(old_self.loose.dom().contains(l2));
1597 assert(self.loose[l2].slot_index != popped_idx);
1598 } else if l2 == new_loose && l1 != new_loose {
1599 assert(old_self.loose.dom().contains(l1));
1600 assert(self.loose[l1].slot_index != popped_idx);
1601 } else if l1 != new_loose && l2 != new_loose {
1602 assert(old_self.loose.dom().contains(l1));
1603 assert(old_self.loose.dom().contains(l2));
1604 }
1605 };
1606
1607 assert(self.cursors == old_self.cursors);
1612 assert(self.lists.dom() =~= old_self.lists.dom());
1613 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1614 &&& self.cursors[cid].list_own.inv()
1615 &&& self.cursors[cid].wf_with_region(self.regions)
1616 } by {
1617 assert(old_self.cursors.dom().contains(cid));
1618 assert(old_self.cursors[cid].wf_with_region(old_regions));
1619 assert(self.cursors[cid].list_own.relate_region(old_regions));
1620 assert(old_self.lists.dom().contains(id));
1621 assert(old_self.lists[id].list_id == old_list_id);
1622 assert(self.cursors[cid].list_own.list_id != old_list_id);
1623 assert(self.cursors[cid].list_own.relate_region(self.regions));
1624 };
1625 assert forall|id2: ListId, cid: CursorId| #[trigger]
1626 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1627 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1628 && self.lists[id2].list_id != 0 implies false by {
1629 assert(old_self.cursors.dom().contains(cid));
1630 assert(old_self.lists.dom().contains(id2));
1631 assert(old_self.lists[id2].list_id == self.lists[id2].list_id);
1632 };
1633 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1634 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1635 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1636 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1637 assert(old_self.cursors.dom().contains(cid1));
1638 assert(old_self.cursors.dom().contains(cid2));
1639 };
1640 Option::Some(new_loose)
1641 }
1642 }
1643
1644 pub proof fn step_insert_before_at(tracked &mut self, id: ListId, n: int, lid: LooseId)
1649 requires
1650 old(self).inv(),
1651 old(self).lists.dom().contains(id),
1652 old(self).loose.dom().contains(lid),
1653 0 <= n <= old(self).lists[id].list.len(),
1654 ensures
1655 final(self).inv(),
1656 {
1657 let ghost old_self = *self;
1658 let ghost old_regions = self.regions;
1659 let ghost fidx = self.loose[lid].slot_index;
1660 let ghost used = Set::<u64>::full().unwrap().filter(
1661 |x: u64|
1662 (exists|i: ListId| #[trigger]
1663 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
1664 || (exists|cid: CursorId| #[trigger]
1665 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
1666 == x),
1667 );
1668 assert(self.lists[id].relate_region(self.regions));
1669 assert(self.loose[lid].global_inv(self.regions));
1670 assert(self.loose[lid].frame_link_inv(self.regions));
1671 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
1672
1673 let tracked mut owner = self.lists.tracked_remove(id);
1674 let tracked mut frame_own = self.loose.tracked_remove(lid);
1675 insert_before_at_embedded(&mut self.regions, &mut owner, &mut frame_own, n, used);
1676 self.lists.tracked_insert(id, owner);
1677 assert(self.loose =~= old_self.loose.remove(lid));
1678 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1679 let ghost new_id = self.lists[id].list_id;
1680
1681 assert forall|i: ListId| #[trigger]
1682 self.lists.dom().contains(i) && i != id && self.lists[i].list_id
1683 != 0 implies self.lists[i].list_id != new_id by {
1684 assert(old_self.lists.dom().contains(i));
1685 assert(old_self.lists[i] == self.lists[i]);
1686 if old_self.lists[id].list_id != 0 {
1687 assert(new_id == old_self.lists[id].list_id);
1688 } else {
1689 assert(used.contains(self.lists[i].list_id));
1690 }
1691 };
1692
1693 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1694 &&& self.lists[i].inv()
1695 &&& self.lists[i].relate_region(self.regions)
1696 } by {
1697 if i != id {
1698 assert(old_self.lists.dom().contains(i));
1699 assert(old_self.lists[i] == self.lists[i]);
1700 assert(old_self.lists[i].relate_region(old_regions));
1701 if self.lists[i].list.len() > 0 {
1702 assert(self.lists[i].list_id != new_id);
1703 }
1704 }
1705 };
1706
1707 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1708 &&& self.loose[lid2].inv()
1709 &&& self.loose[lid2].global_inv(self.regions)
1710 &&& self.loose[lid2].frame_link_inv(self.regions)
1711 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1712 == 0
1713 } by {
1714 assert(lid2 != lid);
1715 assert(old_self.loose.dom().contains(lid2));
1716 assert(old_self.loose[lid2] == self.loose[lid2]);
1717 assert(old_self.loose[lid2].global_inv(old_regions));
1718 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1719 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1720 == 0);
1721 assert(self.loose[lid2].slot_index != fidx);
1722 };
1723
1724 assert forall|i1: ListId, i2: ListId| #[trigger]
1725 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1726 && self.lists[i1].list.len() > 0 && self.lists[i2].list.len() > 0
1727 && self.lists[i1].list_id == self.lists[i2].list_id implies i1 == i2 by {
1728 if i1 != id && i2 != id {
1729 assert(old_self.lists[i1] == self.lists[i1]);
1730 assert(old_self.lists[i2] == self.lists[i2]);
1731 } else if i1 == id && i2 != id {
1732 assert(self.lists[i2].list_id != new_id);
1733 } else if i2 == id && i1 != id {
1734 assert(self.lists[i1].list_id != new_id);
1735 }
1736 };
1737
1738 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1739 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1740 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1741 assert(old_self.loose.dom().contains(l1));
1742 assert(old_self.loose.dom().contains(l2));
1743 };
1744
1745 assert(self.cursors == old_self.cursors);
1753 assert(self.lists.dom() =~= old_self.lists.dom());
1754 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1755 &&& self.cursors[cid].list_own.inv()
1756 &&& self.cursors[cid].wf_with_region(self.regions)
1757 } by {
1758 assert(old_self.cursors.dom().contains(cid));
1759 assert(old_self.cursors[cid].wf_with_region(old_regions));
1760 assert(self.cursors[cid].list_own.relate_region(old_regions));
1761 if old_self.lists[id].list_id != 0 {
1762 assert(new_id == old_self.lists[id].list_id);
1763 } else {
1764 assert(used.contains(self.cursors[cid].list_own.list_id));
1765 }
1766 assert(self.cursors[cid].list_own.list_id != new_id);
1767 assert(self.cursors[cid].list_own.relate_region(self.regions));
1768 };
1769 assert forall|id2: ListId, cid: CursorId| #[trigger]
1770 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1771 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1772 && self.lists[id2].list_id != 0 implies false by {
1773 assert(old_self.cursors.dom().contains(cid));
1774 if id2 == id {
1775 assert(self.lists[id].list_id == new_id);
1776 if old_self.lists[id].list_id != 0 {
1777 assert(new_id == old_self.lists[id].list_id);
1778 } else {
1779 assert(used.contains(self.cursors[cid].list_own.list_id));
1780 }
1781 } else {
1782 assert(old_self.lists.dom().contains(id2));
1783 assert(old_self.lists[id2] == self.lists[id2]);
1784 }
1785 };
1786 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1787 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1788 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1789 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1790 assert(old_self.cursors.dom().contains(cid1));
1791 assert(old_self.cursors.dom().contains(cid2));
1792 };
1793 }
1794
1795 pub proof fn step_take_at(tracked &mut self, id: ListId, n: int) -> (res: Option<LooseId>)
1800 requires
1801 old(self).inv(),
1802 old(self).lists.dom().contains(id),
1803 ensures
1804 final(self).inv(),
1805 !(0 <= n < old(self).lists[id].list.len()) ==> res is None && *final(self) == *old(
1806 self,
1807 ),
1808 0 <= n < old(self).lists[id].list.len() ==> res is Some,
1809 {
1810 if !(0 <= n < self.lists[id].list.len()) {
1811 Option::None
1814 } else {
1815 let ghost old_self = *self;
1816 let ghost old_regions = self.regions;
1817 let ghost popped_idx = self.lists[id].slot_index_at(n);
1818 let ghost old_list_id = self.lists[id].list_id;
1819 assert(self.lists[id].relate_region(self.regions));
1820
1821 let tracked mut owner = self.lists.tracked_remove(id);
1822 let tracked frame_own = take_at_embedded(&mut self.regions, &mut owner, n);
1823 self.lists.tracked_insert(id, owner);
1824 let ghost new_loose = fresh_loose_id(self.loose);
1825 lemma_fresh_loose_id_not_in_dom(self.loose);
1826 self.loose.tracked_insert(new_loose, frame_own);
1827
1828 assert(self.lists =~= old_self.lists.remove(id).insert(id, owner));
1829 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
1830 assert(self.lists[id].list_id == old_list_id);
1831 assert(frame_own.slot_index == popped_idx);
1832
1833 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
1834 &&& self.lists[i].inv()
1835 &&& self.lists[i].relate_region(self.regions)
1836 } by {
1837 if i != id {
1838 assert(old_self.lists.dom().contains(i));
1839 assert(old_self.lists[i] == self.lists[i]);
1840 assert(old_self.lists[i].relate_region(old_regions));
1841 if self.lists[i].list.len() > 0 {
1842 assert(self.lists[i].list_id != old_list_id);
1843 }
1844 }
1845 };
1846
1847 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
1848 &&& self.loose[lid2].inv()
1849 &&& self.loose[lid2].global_inv(self.regions)
1850 &&& self.loose[lid2].frame_link_inv(self.regions)
1851 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1852 == 0
1853 } by {
1854 if lid2 != new_loose {
1855 assert(old_self.loose.dom().contains(lid2));
1856 assert(old_self.loose[lid2] == self.loose[lid2]);
1857 assert(old_self.loose[lid2].global_inv(old_regions));
1858 assert(old_self.loose[lid2].frame_link_inv(old_regions));
1859 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
1860 == 0);
1861 }
1862 };
1863
1864 assert forall|i1: ListId, i2: ListId| #[trigger]
1865 self.lists.dom().contains(i1) && #[trigger] self.lists.dom().contains(i2)
1866 && self.lists[i1].list_id == self.lists[i2].list_id && self.lists[i1].list_id
1867 != 0 implies i1 == i2 by {
1868 assert(old_self.lists.dom().contains(i1));
1869 assert(old_self.lists.dom().contains(i2));
1870 assert(self.lists[i1].list_id == old_self.lists[i1].list_id);
1871 assert(self.lists[i2].list_id == old_self.lists[i2].list_id);
1872 };
1873
1874 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1875 self.loose.dom().contains(l1) && #[trigger] self.loose.dom().contains(l2)
1876 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
1877 if l1 == new_loose && l2 != new_loose {
1878 assert(old_self.loose.dom().contains(l2));
1879 assert(self.loose[l2].slot_index != popped_idx);
1880 } else if l2 == new_loose && l1 != new_loose {
1881 assert(old_self.loose.dom().contains(l1));
1882 assert(self.loose[l1].slot_index != popped_idx);
1883 } else if l1 != new_loose && l2 != new_loose {
1884 assert(old_self.loose.dom().contains(l1));
1885 assert(old_self.loose.dom().contains(l2));
1886 }
1887 };
1888
1889 assert(self.cursors == old_self.cursors);
1894 assert(self.lists.dom() =~= old_self.lists.dom());
1895 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
1896 &&& self.cursors[cid].list_own.inv()
1897 &&& self.cursors[cid].wf_with_region(self.regions)
1898 } by {
1899 assert(old_self.cursors.dom().contains(cid));
1900 assert(old_self.cursors[cid].wf_with_region(old_regions));
1901 assert(self.cursors[cid].list_own.relate_region(old_regions));
1902 assert(old_self.lists.dom().contains(id));
1903 assert(old_self.lists[id].list_id == old_list_id);
1904 assert(self.cursors[cid].list_own.list_id != old_list_id);
1905 assert(self.cursors[cid].list_own.relate_region(self.regions));
1906 };
1907 assert forall|id2: ListId, cid: CursorId| #[trigger]
1908 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
1909 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
1910 && self.lists[id2].list_id != 0 implies false by {
1911 assert(old_self.cursors.dom().contains(cid));
1912 assert(old_self.lists.dom().contains(id2));
1913 assert(old_self.lists[id2].list_id == self.lists[id2].list_id);
1914 };
1915 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
1916 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
1917 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
1918 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
1919 assert(old_self.cursors.dom().contains(cid1));
1920 assert(old_self.cursors.dom().contains(cid2));
1921 };
1922 Option::Some(new_loose)
1923 }
1924 }
1925
1926 proof fn lemma_checkout_inv(old_self: Self, new_self: Self, id: ListId, index: int)
1936 requires
1937 old_self.inv(),
1938 old_self.lists.dom().contains(id),
1939 0 <= index <= old_self.lists[id].list.len(),
1940 new_self.regions == old_self.regions,
1941 new_self.loose == old_self.loose,
1942 new_self.lists == old_self.lists.remove(id),
1943 new_self.cursors == old_self.cursors.insert(
1944 id,
1945 CursorOwner::cursor_mut_at_owner(old_self.lists[id], index),
1946 ),
1947 ensures
1948 new_self.inv(),
1949 {
1950 assert forall|i: ListId| #[trigger] new_self.lists.dom().contains(i) implies {
1951 &&& new_self.lists[i].inv()
1952 &&& new_self.lists[i].relate_region(new_self.regions)
1953 } by {
1954 assert(i != id);
1955 assert(old_self.lists.dom().contains(i));
1956 assert(old_self.lists[i] == new_self.lists[i]);
1957 };
1958 assert forall|lid: LooseId| #[trigger] new_self.loose.dom().contains(lid) implies {
1959 &&& new_self.loose[lid].inv()
1960 &&& new_self.loose[lid].global_inv(new_self.regions)
1961 &&& new_self.loose[lid].frame_link_inv(new_self.regions)
1962 &&& new_self.regions.slot_owners[new_self.loose[lid].slot_index].inner_perms.in_list.value()
1963 == 0
1964 } by {
1965 assert(old_self.loose.dom().contains(lid));
1966 };
1967 assert forall|i1: ListId, i2: ListId| #[trigger]
1968 new_self.lists.dom().contains(i1) && #[trigger] new_self.lists.dom().contains(i2)
1969 && new_self.lists[i1].list_id == new_self.lists[i2].list_id
1970 && new_self.lists[i1].list_id != 0 implies i1 == i2 by {
1971 assert(old_self.lists.dom().contains(i1));
1972 assert(old_self.lists.dom().contains(i2));
1973 };
1974 assert forall|l1: LooseId, l2: LooseId| #[trigger]
1975 new_self.loose.dom().contains(l1) && #[trigger] new_self.loose.dom().contains(l2)
1976 && new_self.loose[l1].slot_index == new_self.loose[l2].slot_index implies l1
1977 == l2 by {
1978 assert(old_self.loose.dom().contains(l1));
1979 assert(old_self.loose.dom().contains(l2));
1980 };
1981 assert(new_self.lists.dom().disjoint(new_self.cursors.dom()));
1982 assert forall|cid: CursorId| #[trigger] new_self.cursors.dom().contains(cid) implies {
1983 &&& new_self.cursors[cid].list_own.inv()
1984 &&& new_self.cursors[cid].wf_with_region(new_self.regions)
1985 } by {
1986 if cid != id {
1987 assert(old_self.cursors.dom().contains(cid));
1988 } else {
1989 assert(new_self.cursors[id].list_own == old_self.lists[id]);
1990 assert(old_self.lists[id].relate_region(old_self.regions));
1991 }
1992 };
1993 assert forall|id2: ListId, cid: CursorId| #[trigger]
1994 new_self.lists.dom().contains(id2) && #[trigger] new_self.cursors.dom().contains(cid)
1995 && new_self.lists[id2].list_id == new_self.cursors[cid].list_own.list_id
1996 && new_self.lists[id2].list_id != 0 implies false by {
1997 assert(id2 != id);
1998 assert(old_self.lists.dom().contains(id2));
1999 assert(old_self.lists[id2] == new_self.lists[id2]);
2000 if cid == id {
2001 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2002 assert(old_self.lists.dom().contains(id));
2003 } else {
2004 assert(old_self.cursors.dom().contains(cid));
2005 assert(old_self.cursors[cid] == new_self.cursors[cid]);
2006 }
2007 };
2008 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2009 new_self.cursors.dom().contains(cid1) && #[trigger] new_self.cursors.dom().contains(
2010 cid2,
2011 ) && new_self.cursors[cid1].list_own.list_id == new_self.cursors[cid2].list_own.list_id
2012 && new_self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2013 if cid1 == id && cid2 != id {
2014 assert(old_self.cursors.dom().contains(cid2));
2015 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2016 assert(old_self.lists.dom().contains(id));
2017 } else if cid2 == id && cid1 != id {
2018 assert(old_self.cursors.dom().contains(cid1));
2019 assert(new_self.cursors[id].list_own == old_self.lists[id]);
2020 assert(old_self.lists.dom().contains(id));
2021 } else if cid1 != id && cid2 != id {
2022 assert(old_self.cursors.dom().contains(cid1));
2023 assert(old_self.cursors.dom().contains(cid2));
2024 }
2025 };
2026 }
2027
2028 proof fn lemma_checkin_inv(old_self: Self, new_self: Self, id: CursorId)
2032 requires
2033 old_self.inv(),
2034 old_self.cursors.dom().contains(id),
2035 new_self.regions == old_self.regions,
2036 new_self.loose == old_self.loose,
2037 new_self.cursors == old_self.cursors.remove(id),
2038 new_self.lists == old_self.lists.insert(id, old_self.cursors[id].list_own),
2039 ensures
2040 new_self.inv(),
2041 {
2042 assert(!old_self.lists.dom().contains(id));
2043 assert forall|i: ListId| #[trigger] new_self.lists.dom().contains(i) implies {
2044 &&& new_self.lists[i].inv()
2045 &&& new_self.lists[i].relate_region(new_self.regions)
2046 } by {
2047 if i == id {
2048 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2049 assert(old_self.cursors[id].wf_with_region(old_self.regions));
2050 } else {
2051 assert(old_self.lists.dom().contains(i));
2052 assert(old_self.lists[i] == new_self.lists[i]);
2053 }
2054 };
2055 assert forall|lid: LooseId| #[trigger] new_self.loose.dom().contains(lid) implies {
2056 &&& new_self.loose[lid].inv()
2057 &&& new_self.loose[lid].global_inv(new_self.regions)
2058 &&& new_self.loose[lid].frame_link_inv(new_self.regions)
2059 &&& new_self.regions.slot_owners[new_self.loose[lid].slot_index].inner_perms.in_list.value()
2060 == 0
2061 } by {
2062 assert(old_self.loose.dom().contains(lid));
2063 };
2064 assert forall|i1: ListId, i2: ListId| #[trigger]
2065 new_self.lists.dom().contains(i1) && #[trigger] new_self.lists.dom().contains(i2)
2066 && new_self.lists[i1].list_id == new_self.lists[i2].list_id
2067 && new_self.lists[i1].list_id != 0 implies i1 == i2 by {
2068 if i1 == id && i2 != id {
2072 assert(old_self.lists.dom().contains(i2));
2073 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2074 assert(old_self.cursors.dom().contains(id));
2075 } else if i2 == id && i1 != id {
2076 assert(old_self.lists.dom().contains(i1));
2077 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2078 assert(old_self.cursors.dom().contains(id));
2079 } else if i1 != id && i2 != id {
2080 assert(old_self.lists.dom().contains(i1));
2081 assert(old_self.lists.dom().contains(i2));
2082 }
2083 };
2084 assert forall|l1: LooseId, l2: LooseId| #[trigger]
2085 new_self.loose.dom().contains(l1) && #[trigger] new_self.loose.dom().contains(l2)
2086 && new_self.loose[l1].slot_index == new_self.loose[l2].slot_index implies l1
2087 == l2 by {
2088 assert(old_self.loose.dom().contains(l1));
2089 assert(old_self.loose.dom().contains(l2));
2090 };
2091 assert(new_self.lists.dom().disjoint(new_self.cursors.dom()));
2092 assert forall|cid: CursorId| #[trigger] new_self.cursors.dom().contains(cid) implies {
2093 &&& new_self.cursors[cid].list_own.inv()
2094 &&& new_self.cursors[cid].wf_with_region(new_self.regions)
2095 } by {
2096 assert(cid != id);
2097 assert(old_self.cursors.dom().contains(cid));
2098 assert(old_self.cursors[cid] == new_self.cursors[cid]);
2099 };
2100 assert forall|id2: ListId, cid: CursorId| #[trigger]
2101 new_self.lists.dom().contains(id2) && #[trigger] new_self.cursors.dom().contains(cid)
2102 && new_self.lists[id2].list_id == new_self.cursors[cid].list_own.list_id
2103 && new_self.lists[id2].list_id != 0 implies false by {
2104 assert(cid != id);
2105 assert(old_self.cursors.dom().contains(cid));
2106 assert(old_self.cursors[cid] == new_self.cursors[cid]);
2107 if id2 == id {
2108 assert(new_self.lists[id] == old_self.cursors[id].list_own);
2109 assert(old_self.cursors.dom().contains(id));
2110 } else {
2111 assert(old_self.lists.dom().contains(id2));
2112 assert(old_self.lists[id2] == new_self.lists[id2]);
2113 }
2114 };
2115 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2116 new_self.cursors.dom().contains(cid1) && #[trigger] new_self.cursors.dom().contains(
2117 cid2,
2118 ) && new_self.cursors[cid1].list_own.list_id == new_self.cursors[cid2].list_own.list_id
2119 && new_self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2120 assert(old_self.cursors.dom().contains(cid1));
2121 assert(old_self.cursors.dom().contains(cid2));
2122 };
2123 }
2124
2125 proof fn lemma_revise_cursor_inv(old_self: Self, new_self: Self, id: CursorId)
2130 requires
2131 old_self.inv(),
2132 old_self.cursors.dom().contains(id),
2133 new_self.regions == old_self.regions,
2134 new_self.lists == old_self.lists,
2135 new_self.loose == old_self.loose,
2136 new_self.cursors.dom() == old_self.cursors.dom(),
2137 new_self.cursors[id].list_own == old_self.cursors[id].list_own,
2138 0 <= new_self.cursors[id].index <= new_self.cursors[id].list_own.list.len(),
2139 forall|c: CursorId| #[trigger]
2140 new_self.cursors.dom().contains(c) && c != id ==> new_self.cursors[c]
2141 == old_self.cursors[c],
2142 ensures
2143 new_self.inv(),
2144 {
2145 assert forall|i: ListId| #[trigger] new_self.lists.dom().contains(i) implies {
2146 &&& new_self.lists[i].inv()
2147 &&& new_self.lists[i].relate_region(new_self.regions)
2148 } by {
2149 assert(old_self.lists.dom().contains(i));
2150 };
2151 assert forall|lid: LooseId| #[trigger] new_self.loose.dom().contains(lid) implies {
2152 &&& new_self.loose[lid].inv()
2153 &&& new_self.loose[lid].global_inv(new_self.regions)
2154 &&& new_self.loose[lid].frame_link_inv(new_self.regions)
2155 &&& new_self.regions.slot_owners[new_self.loose[lid].slot_index].inner_perms.in_list.value()
2156 == 0
2157 } by {
2158 assert(old_self.loose.dom().contains(lid));
2159 };
2160 assert forall|i1: ListId, i2: ListId| #[trigger]
2161 new_self.lists.dom().contains(i1) && #[trigger] new_self.lists.dom().contains(i2)
2162 && new_self.lists[i1].list_id == new_self.lists[i2].list_id
2163 && new_self.lists[i1].list_id != 0 implies i1 == i2 by {
2164 assert(old_self.lists.dom().contains(i1));
2165 assert(old_self.lists.dom().contains(i2));
2166 };
2167 assert forall|l1: LooseId, l2: LooseId| #[trigger]
2168 new_self.loose.dom().contains(l1) && #[trigger] new_self.loose.dom().contains(l2)
2169 && new_self.loose[l1].slot_index == new_self.loose[l2].slot_index implies l1
2170 == l2 by {
2171 assert(old_self.loose.dom().contains(l1));
2172 assert(old_self.loose.dom().contains(l2));
2173 };
2174 assert(new_self.lists.dom().disjoint(new_self.cursors.dom()));
2175 assert forall|cid: CursorId| #[trigger] new_self.cursors.dom().contains(cid) implies {
2176 &&& new_self.cursors[cid].list_own.inv()
2177 &&& new_self.cursors[cid].wf_with_region(new_self.regions)
2178 } by {
2179 assert(old_self.cursors.dom().contains(cid));
2180 if cid != id {
2181 assert(new_self.cursors[cid] == old_self.cursors[cid]);
2182 } else {
2183 assert(new_self.cursors[id].list_own == old_self.cursors[id].list_own);
2184 assert(old_self.cursors[id].wf_with_region(old_self.regions));
2185 }
2186 };
2187 assert forall|id2: ListId, cid: CursorId| #[trigger]
2188 new_self.lists.dom().contains(id2) && #[trigger] new_self.cursors.dom().contains(cid)
2189 && new_self.lists[id2].list_id == new_self.cursors[cid].list_own.list_id
2190 && new_self.lists[id2].list_id != 0 implies false by {
2191 assert(old_self.lists.dom().contains(id2));
2192 assert(old_self.cursors.dom().contains(cid));
2193 assert(new_self.cursors[cid].list_own.list_id
2194 == old_self.cursors[cid].list_own.list_id);
2195 };
2196 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2197 new_self.cursors.dom().contains(cid1) && #[trigger] new_self.cursors.dom().contains(
2198 cid2,
2199 ) && new_self.cursors[cid1].list_own.list_id == new_self.cursors[cid2].list_own.list_id
2200 && new_self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2201 assert(old_self.cursors.dom().contains(cid1));
2202 assert(old_self.cursors.dom().contains(cid2));
2203 assert(new_self.cursors[cid1].list_own.list_id
2204 == old_self.cursors[cid1].list_own.list_id);
2205 assert(new_self.cursors[cid2].list_own.list_id
2206 == old_self.cursors[cid2].list_own.list_id);
2207 };
2208 }
2209
2210 pub proof fn step_cursor_front_mut(tracked &mut self, id: ListId)
2214 requires
2215 old(self).inv(),
2216 old(self).lists.dom().contains(id),
2217 ensures
2218 final(self).inv(),
2219 !final(self).lists.dom().contains(id),
2220 final(self).cursors.dom().contains(id),
2221 final(self).cursors[id] == CursorOwner::front_owner(old(self).lists[id]),
2222 {
2223 let ghost old_self = *self;
2224 let tracked owner = self.lists.tracked_remove(id);
2225 let tracked cur = CursorOwner::tracked_front_owner(owner);
2226 self.cursors.tracked_insert(id, cur);
2227 assert(self.lists =~= old_self.lists.remove(id));
2228 assert(self.cursors =~= old_self.cursors.insert(
2229 id,
2230 CursorOwner::cursor_mut_at_owner(old_self.lists[id], 0),
2231 ));
2232 Self::lemma_checkout_inv(old_self, *self, id, 0);
2233 }
2234
2235 pub proof fn step_cursor_back_mut(tracked &mut self, id: ListId)
2238 requires
2239 old(self).inv(),
2240 old(self).lists.dom().contains(id),
2241 ensures
2242 final(self).inv(),
2243 !final(self).lists.dom().contains(id),
2244 final(self).cursors.dom().contains(id),
2245 final(self).cursors[id] == CursorOwner::back_owner(old(self).lists[id]),
2246 {
2247 let ghost old_self = *self;
2248 let tracked owner = self.lists.tracked_remove(id);
2249 let ghost bidx = CursorOwner::back_owner(owner).index;
2250 let tracked cur = CursorOwner::tracked_back_owner(owner);
2251 self.cursors.tracked_insert(id, cur);
2252 assert(self.lists =~= old_self.lists.remove(id));
2253 assert(self.cursors =~= old_self.cursors.insert(
2254 id,
2255 CursorOwner::cursor_mut_at_owner(old_self.lists[id], bidx),
2256 ));
2257 Self::lemma_checkout_inv(old_self, *self, id, bidx);
2258 }
2259
2260 pub proof fn step_cursor_mut_at(tracked &mut self, id: ListId, frame: Paddr) -> (res: bool)
2267 requires
2268 old(self).inv(),
2269 old(self).lists.dom().contains(id),
2270 ensures
2271 final(self).inv(),
2272 res == (exists|i: int|
2274 0 <= i < old(self).lists[id].list.len() && old(self).lists[id].slot_index_at(i)
2275 == frame_to_index(frame)),
2276 res ==> !final(self).lists.dom().contains(id) && final(self).cursors.dom().contains(id)
2279 && exists|i: int|
2280 0 <= i < old(self).lists[id].list.len() && old(self).lists[id].slot_index_at(i)
2281 == frame_to_index(frame) && final(self).cursors[id]
2282 == CursorOwner::cursor_mut_at_owner(old(self).lists[id], i),
2283 !res ==> *final(self) == *old(self),
2285 {
2286 if exists|i: int|
2287 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i) == frame_to_index(
2288 frame,
2289 ) {
2290 let ghost index = choose|i: int|
2291 0 <= i < self.lists[id].list.len() && self.lists[id].slot_index_at(i)
2292 == frame_to_index(frame);
2293 let ghost old_self = *self;
2294 let tracked owner = self.lists.tracked_remove(id);
2295 let tracked cur = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
2296 self.cursors.tracked_insert(id, cur);
2297 assert(self.lists =~= old_self.lists.remove(id));
2298 assert(self.cursors =~= old_self.cursors.insert(
2299 id,
2300 CursorOwner::cursor_mut_at_owner(old_self.lists[id], index),
2301 ));
2302 Self::lemma_checkout_inv(old_self, *self, id, index);
2303 true
2304 } else {
2305 false
2306 }
2307 }
2308
2309 pub proof fn step_move_next(tracked &mut self, id: CursorId)
2312 requires
2313 old(self).inv(),
2314 old(self).cursors.dom().contains(id),
2315 ensures
2316 final(self).inv(),
2317 final(self).regions == old(self).regions,
2318 final(self).cursors[id] == old(self).cursors[id].move_next_owner_spec(),
2319 {
2320 let ghost old_self = *self;
2321 let tracked cur = self.cursors.tracked_remove(id);
2322 let ghost ni = cur.move_next_owner_spec().index;
2323 let tracked CursorOwner { list_own, index: _ } = cur;
2324 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(list_own, ni);
2325 self.cursors.tracked_insert(id, cur2);
2326 assert(self.cursors[id] == old_self.cursors[id].move_next_owner_spec());
2327 assert(self.cursors.dom() =~= old_self.cursors.dom());
2328 Self::lemma_revise_cursor_inv(old_self, *self, id);
2329 }
2330
2331 pub proof fn step_move_prev(tracked &mut self, id: CursorId)
2334 requires
2335 old(self).inv(),
2336 old(self).cursors.dom().contains(id),
2337 ensures
2338 final(self).inv(),
2339 final(self).regions == old(self).regions,
2340 final(self).cursors[id] == old(self).cursors[id].move_prev_owner_spec(),
2341 {
2342 let ghost old_self = *self;
2343 let tracked cur = self.cursors.tracked_remove(id);
2344 let ghost ni = cur.move_prev_owner_spec().index;
2345 let tracked CursorOwner { list_own, index: _ } = cur;
2346 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(list_own, ni);
2347 self.cursors.tracked_insert(id, cur2);
2348 assert(self.cursors[id] == old_self.cursors[id].move_prev_owner_spec());
2349 assert(self.cursors.dom() =~= old_self.cursors.dom());
2350 Self::lemma_revise_cursor_inv(old_self, *self, id);
2351 }
2352
2353 pub proof fn step_current_meta(tracked &self, id: CursorId) -> (res: Option<LinkOwner>)
2357 requires
2358 self.inv(),
2359 self.cursors.dom().contains(id),
2360 ensures
2361 res == self.cursors[id].current(),
2362 res.is_some() <==> 0 <= self.cursors[id].index < self.cursors[id].length(),
2363 {
2364 self.cursors[id].current()
2365 }
2366
2367 pub proof fn step_as_list(tracked &self, id: CursorId) -> (res: Seq<LinkOwner>)
2373 requires
2374 self.inv(),
2375 self.cursors.dom().contains(id),
2376 ensures
2377 res == self.cursors[id].list_own.list,
2378 res.len() == self.cursors[id].length(),
2379 {
2380 self.cursors[id].list_own.list
2381 }
2382
2383 pub proof fn step_cursor_drop(tracked &mut self, id: CursorId)
2387 requires
2388 old(self).inv(),
2389 old(self).cursors.dom().contains(id),
2390 ensures
2391 final(self).inv(),
2392 !final(self).cursors.dom().contains(id),
2393 final(self).lists.dom().contains(id),
2394 final(self).lists[id] == old(self).cursors[id].list_own,
2395 {
2396 let ghost old_self = *self;
2397 let tracked cur = self.cursors.tracked_remove(id);
2398 let tracked CursorOwner { list_own, index: _ } = cur;
2399 self.lists.tracked_insert(id, list_own);
2400 assert(self.cursors =~= old_self.cursors.remove(id));
2401 assert(self.lists =~= old_self.lists.insert(id, old_self.cursors[id].list_own));
2402 Self::lemma_checkin_inv(old_self, *self, id);
2403 }
2404
2405 pub proof fn step_cursor_insert_before(tracked &mut self, id: CursorId, lid: LooseId)
2412 requires
2413 old(self).inv(),
2414 old(self).cursors.dom().contains(id),
2415 old(self).loose.dom().contains(lid),
2416 ensures
2417 final(self).inv(),
2418 {
2419 let ghost old_self = *self;
2420 let ghost old_regions = self.regions;
2421 let ghost fidx = self.loose[lid].slot_index;
2422 let ghost n = self.cursors[id].index;
2423 let ghost used = Set::<u64>::full().unwrap().filter(
2425 |x: u64|
2426 (exists|i: ListId| #[trigger]
2427 old_self.lists.dom().contains(i) && old_self.lists[i].list_id == x) || (exists|
2428 cid: CursorId,
2429 | #[trigger]
2430 old_self.cursors.dom().contains(cid) && cid != id
2431 && old_self.cursors[cid].list_own.list_id == x),
2432 );
2433 assert(self.cursors[id].wf_with_region(self.regions));
2434 assert(self.cursors[id].list_own.relate_region(self.regions));
2435 assert(self.loose[lid].global_inv(self.regions));
2436 assert(self.loose[lid].frame_link_inv(self.regions));
2437 assert(self.regions.slot_owners[fidx].inner_perms.in_list.value() == 0);
2438
2439 let tracked cur = self.cursors.tracked_remove(id);
2440 let tracked CursorOwner { list_own: mut owner, index: _ } = cur;
2441 let tracked mut frame_own = self.loose.tracked_remove(lid);
2442 insert_before_at_embedded(&mut self.regions, &mut owner, &mut frame_own, n, used);
2443 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(owner, n + 1);
2444 self.cursors.tracked_insert(id, cur2);
2445 assert(self.loose =~= old_self.loose.remove(lid));
2446 assert(self.cursors =~= old_self.cursors.remove(id).insert(id, cur2));
2447 let ghost new_id = self.cursors[id].list_own.list_id;
2448 assert(self.cursors[id].list_own == owner);
2449
2450 assert forall|i: ListId| #[trigger]
2454 old_self.lists.dom().contains(i) && self.lists[i].list_id
2455 != 0 implies self.lists[i].list_id != new_id by {
2456 if old_self.cursors[id].list_own.list_id != 0 {
2457 assert(new_id == old_self.cursors[id].list_own.list_id);
2458 assert(old_self.cursors.dom().contains(id));
2459 } else {
2460 assert(used.contains(self.lists[i].list_id));
2461 }
2462 };
2463 assert forall|cid: CursorId| #[trigger]
2464 old_self.cursors.dom().contains(cid) && cid != id
2465 && old_self.cursors[cid].list_own.list_id
2466 != 0 implies old_self.cursors[cid].list_own.list_id != new_id by {
2467 if old_self.cursors[id].list_own.list_id != 0 {
2468 assert(new_id == old_self.cursors[id].list_own.list_id);
2469 } else {
2470 assert(used.contains(old_self.cursors[cid].list_own.list_id));
2471 }
2472 };
2473
2474 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
2476 &&& self.lists[i].inv()
2477 &&& self.lists[i].relate_region(self.regions)
2478 } by {
2479 assert(old_self.lists.dom().contains(i));
2480 assert(old_self.lists[i] == self.lists[i]);
2481 assert(old_self.lists[i].relate_region(old_regions));
2482 assert(self.lists[i].list_id != new_id);
2483 assert(self.lists[i].relate_region(self.regions));
2484 };
2485
2486 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
2488 &&& self.loose[lid2].inv()
2489 &&& self.loose[lid2].global_inv(self.regions)
2490 &&& self.loose[lid2].frame_link_inv(self.regions)
2491 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2492 == 0
2493 } by {
2494 assert(lid2 != lid);
2495 assert(old_self.loose.dom().contains(lid2));
2496 assert(old_self.loose[lid2] == self.loose[lid2]);
2497 assert(old_self.loose[lid2].global_inv(old_regions));
2498 assert(old_self.loose[lid2].frame_link_inv(old_regions));
2499 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2500 == 0);
2501 assert(self.loose[lid2].slot_index != fidx);
2502 };
2503
2504 assert(self.lists.dom() =~= old_self.lists.dom());
2506 assert(self.cursors.dom() =~= old_self.cursors.dom());
2507 assert(self.lists.dom().disjoint(self.cursors.dom()));
2508
2509 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
2511 &&& self.cursors[cid].list_own.inv()
2512 &&& self.cursors[cid].wf_with_region(self.regions)
2513 } by {
2514 if cid == id {
2515 assert(self.cursors[id].list_own == owner);
2516 assert(self.cursors[id].index == n + 1);
2517 assert(owner.list.len() == old_self.cursors[id].list_own.list.len() + 1);
2518 } else {
2519 assert(old_self.cursors.dom().contains(cid));
2520 assert(old_self.cursors[cid] == self.cursors[cid]);
2521 assert(old_self.cursors[cid].wf_with_region(old_regions));
2522 assert(self.cursors[cid].list_own.relate_region(old_regions));
2523 assert(self.cursors[cid].list_own.list_id != new_id);
2524 assert(self.cursors[cid].list_own.relate_region(self.regions));
2525 }
2526 };
2527
2528 assert forall|id2: ListId, cid: CursorId| #[trigger]
2530 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
2531 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
2532 && self.lists[id2].list_id != 0 implies false by {
2533 assert(old_self.lists.dom().contains(id2));
2534 assert(old_self.lists[id2] == self.lists[id2]);
2535 if cid == id {
2536 assert(self.cursors[id].list_own.list_id == new_id);
2537 assert(self.lists[id2].list_id != new_id);
2538 } else {
2539 assert(old_self.cursors.dom().contains(cid));
2540 assert(old_self.cursors[cid] == self.cursors[cid]);
2541 }
2542 };
2543
2544 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2546 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
2547 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
2548 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2549 if cid1 == id && cid2 != id {
2550 assert(self.cursors[id].list_own.list_id == new_id);
2551 assert(old_self.cursors.dom().contains(cid2));
2552 assert(old_self.cursors[cid2] == self.cursors[cid2]);
2553 assert(self.cursors[cid2].list_own.list_id != new_id);
2554 } else if cid2 == id && cid1 != id {
2555 assert(self.cursors[id].list_own.list_id == new_id);
2556 assert(old_self.cursors.dom().contains(cid1));
2557 assert(old_self.cursors[cid1] == self.cursors[cid1]);
2558 assert(self.cursors[cid1].list_own.list_id != new_id);
2559 } else if cid1 != id && cid2 != id {
2560 assert(old_self.cursors.dom().contains(cid1));
2561 assert(old_self.cursors.dom().contains(cid2));
2562 }
2563 };
2564 }
2565
2566 pub proof fn step_cursor_take_current(tracked &mut self, id: CursorId) -> (res: Option<LooseId>)
2573 requires
2574 old(self).inv(),
2575 old(self).cursors.dom().contains(id),
2576 ensures
2577 final(self).inv(),
2578 !(0 <= old(self).cursors[id].index < old(self).cursors[id].length()) ==> res is None
2579 && *final(self) == *old(self),
2580 0 <= old(self).cursors[id].index < old(self).cursors[id].length() ==> res is Some,
2581 {
2582 if !(0 <= self.cursors[id].index < self.cursors[id].length()) {
2583 Option::None
2586 } else {
2587 let ghost old_self = *self;
2588 let ghost old_regions = self.regions;
2589 let ghost n = self.cursors[id].index;
2590 let ghost old_list_id = self.cursors[id].list_own.list_id;
2591 let ghost popped_idx = self.cursors[id].list_own.slot_index_at(n);
2592 assert(self.cursors[id].list_own.relate_region(self.regions));
2593 assert(old_list_id != 0);
2595
2596 let tracked cur = self.cursors.tracked_remove(id);
2597 let tracked CursorOwner { list_own: mut owner, index: _ } = cur;
2598 let tracked frame_own = take_at_embedded(&mut self.regions, &mut owner, n);
2599 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(owner, n);
2600 self.cursors.tracked_insert(id, cur2);
2601 let ghost new_loose = fresh_loose_id(self.loose);
2602 lemma_fresh_loose_id_not_in_dom(self.loose);
2603 self.loose.tracked_insert(new_loose, frame_own);
2604
2605 assert(self.cursors =~= old_self.cursors.remove(id).insert(id, cur2));
2606 assert(self.loose =~= old_self.loose.insert(new_loose, frame_own));
2607 assert(self.cursors[id].list_own.list_id == old_list_id);
2608 assert(self.cursors[id].list_own == owner);
2609 assert(frame_own.slot_index == popped_idx);
2610
2611 assert forall|i: ListId| #[trigger] self.lists.dom().contains(i) implies {
2613 &&& self.lists[i].inv()
2614 &&& self.lists[i].relate_region(self.regions)
2615 } by {
2616 assert(old_self.lists.dom().contains(i));
2617 assert(old_self.lists[i] == self.lists[i]);
2618 assert(old_self.lists[i].relate_region(old_regions));
2619 assert(old_self.cursors.dom().contains(id));
2620 assert(self.lists[i].list_id != old_list_id);
2621 assert(self.lists[i].relate_region(self.regions));
2622 };
2623
2624 assert forall|lid2: LooseId| #[trigger] self.loose.dom().contains(lid2) implies {
2627 &&& self.loose[lid2].inv()
2628 &&& self.loose[lid2].global_inv(self.regions)
2629 &&& self.loose[lid2].frame_link_inv(self.regions)
2630 &&& self.regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2631 == 0
2632 } by {
2633 if lid2 != new_loose {
2634 assert(old_self.loose.dom().contains(lid2));
2635 assert(old_self.loose[lid2] == self.loose[lid2]);
2636 assert(old_self.loose[lid2].global_inv(old_regions));
2637 assert(old_self.loose[lid2].frame_link_inv(old_regions));
2638 assert(old_regions.slot_owners[self.loose[lid2].slot_index].inner_perms.in_list.value()
2639 == 0);
2640 }
2641 };
2642
2643 assert(self.lists.dom() =~= old_self.lists.dom());
2645 assert(self.cursors.dom() =~= old_self.cursors.dom());
2646 assert(self.lists.dom().disjoint(self.cursors.dom()));
2647
2648 assert forall|cid: CursorId| #[trigger] self.cursors.dom().contains(cid) implies {
2650 &&& self.cursors[cid].list_own.inv()
2651 &&& self.cursors[cid].wf_with_region(self.regions)
2652 } by {
2653 if cid == id {
2654 assert(self.cursors[id].list_own == owner);
2655 assert(self.cursors[id].index == n);
2656 assert(owner.list.len() == old_self.cursors[id].list_own.list.len() - 1);
2657 } else {
2658 assert(old_self.cursors.dom().contains(cid));
2659 assert(old_self.cursors[cid] == self.cursors[cid]);
2660 assert(old_self.cursors[cid].wf_with_region(old_regions));
2661 assert(self.cursors[cid].list_own.relate_region(old_regions));
2662 assert(self.cursors[cid].list_own.list_id != old_list_id);
2663 assert(self.cursors[cid].list_own.relate_region(self.regions));
2664 }
2665 };
2666
2667 assert forall|id2: ListId, cid: CursorId| #[trigger]
2669 self.lists.dom().contains(id2) && #[trigger] self.cursors.dom().contains(cid)
2670 && self.lists[id2].list_id == self.cursors[cid].list_own.list_id
2671 && self.lists[id2].list_id != 0 implies false by {
2672 assert(old_self.lists.dom().contains(id2));
2673 assert(old_self.lists[id2] == self.lists[id2]);
2674 if cid == id {
2675 assert(self.cursors[id].list_own.list_id == old_list_id);
2676 assert(self.lists[id2].list_id != old_list_id);
2677 } else {
2678 assert(old_self.cursors.dom().contains(cid));
2679 assert(old_self.cursors[cid] == self.cursors[cid]);
2680 }
2681 };
2682
2683 assert forall|cid1: CursorId, cid2: CursorId| #[trigger]
2685 self.cursors.dom().contains(cid1) && #[trigger] self.cursors.dom().contains(cid2)
2686 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
2687 && self.cursors[cid1].list_own.list_id != 0 implies cid1 == cid2 by {
2688 assert(old_self.cursors.dom().contains(cid1));
2689 assert(old_self.cursors.dom().contains(cid2));
2690 assert(self.cursors[cid1].list_own.list_id
2691 == old_self.cursors[cid1].list_own.list_id);
2692 assert(self.cursors[cid2].list_own.list_id
2693 == old_self.cursors[cid2].list_own.list_id);
2694 };
2695
2696 assert forall|l1: LooseId, l2: LooseId|
2698 #![trigger self.loose.dom().contains(l1), self.loose.dom().contains(l2)]
2699 self.loose.dom().contains(l1) && self.loose.dom().contains(l2)
2700 && self.loose[l1].slot_index == self.loose[l2].slot_index implies l1 == l2 by {
2701 if l1 == new_loose && l2 != new_loose {
2702 assert(old_self.loose.dom().contains(l2));
2703 assert(self.loose[l2].slot_index != popped_idx);
2704 } else if l2 == new_loose && l1 != new_loose {
2705 assert(old_self.loose.dom().contains(l1));
2706 assert(self.loose[l1].slot_index != popped_idx);
2707 } else if l1 != new_loose && l2 != new_loose {
2708 assert(old_self.loose.dom().contains(l1));
2709 assert(old_self.loose.dom().contains(l2));
2710 }
2711 };
2712 Option::Some(new_loose)
2713 }
2714 }
2715}
2716
2717}