1use super::super::super::map::*;
77use super::super::super::map_lib::*;
78use super::super::super::modes::*;
79use super::super::super::prelude::*;
80use super::super::super::set_lib::*;
81use super::super::Loc;
82use super::super::algebra::ResourceAlgebra;
83#[cfg(verus_keep_ghost)]
84use super::super::incorporate;
85use super::super::pcm::PCM;
86use super::super::pcm::Resource;
87#[cfg(verus_keep_ghost)]
88use super::super::split_mut;
89
90verus! {
91
92broadcast use {super::super::super::group_vstd_default, super::super::super::map::group_map_lemmas};
93
94#[verifier::reject_recursive_types(K)]
95#[verifier::ext_equal]
96enum AuthCarrier<K, V> {
97 Auth(Map<K, V>),
98 Frac,
99 Invalid,
100}
101
102#[verifier::reject_recursive_types(K)]
103#[verifier::ext_equal]
104enum FracCarrier<K, V> {
105 Frac { owning: Map<K, V>, dup: Map<K, V> },
106 Invalid,
107}
108
109impl<K, V> AuthCarrier<K, V> {
110 spec fn valid(self) -> bool {
111 !(self is Invalid)
112 }
113
114 spec fn map(self) -> Map<K, V>
115 recommends
116 self.valid(),
117 {
118 match self {
119 AuthCarrier::Auth(m) => m,
120 AuthCarrier::Frac => Map::empty(),
121 AuthCarrier::Invalid => Map::empty(),
122 }
123 }
124}
125
126impl<K, V> FracCarrier<K, V> {
127 spec fn valid(self) -> bool {
128 match self {
129 FracCarrier::Invalid => false,
130 FracCarrier::Frac { owning, dup } => owning.dom().disjoint(dup.dom()),
131 }
132 }
133
134 spec fn owning_map(self) -> Map<K, V> {
135 match self {
136 FracCarrier::Frac { owning, .. } => owning,
137 FracCarrier::Invalid => Map::empty(),
138 }
139 }
140
141 spec fn dup_map(self) -> Map<K, V> {
142 match self {
143 FracCarrier::Frac { dup, .. } => dup,
144 FracCarrier::Invalid => Map::empty(),
145 }
146 }
147}
148
149#[verifier::reject_recursive_types(K)]
150#[verifier::ext_equal]
151tracked struct MapCarrier<K, V> {
153 auth: AuthCarrier<K, V>,
154 frac: FracCarrier<K, V>,
155}
156
157impl<K, V> ResourceAlgebra for MapCarrier<K, V> {
158 closed spec fn valid(self) -> bool {
159 match (self.auth, self.frac) {
160 (AuthCarrier::Invalid, _) => false,
161 (_, FracCarrier::Invalid) => false,
162 (AuthCarrier::Auth(auth), FracCarrier::Frac { owning, dup }) => {
163 &&& owning <= auth
164 &&& dup <= auth
165 &&& owning.dom().disjoint(dup.dom())
166 },
167 (AuthCarrier::Frac, FracCarrier::Frac { owning, dup }) => owning.dom().disjoint(
168 dup.dom(),
169 ),
170 }
171 }
172
173 closed spec fn op(a: Self, b: Self) -> Self {
174 let auth = match (a.auth, b.auth) {
175 (AuthCarrier::Invalid, _) => AuthCarrier::Invalid,
177 (_, AuthCarrier::Invalid) => AuthCarrier::Invalid,
178 (AuthCarrier::Auth(_), AuthCarrier::Auth(_)) => AuthCarrier::Invalid,
180 (AuthCarrier::Frac, AuthCarrier::Frac) => AuthCarrier::Frac,
182 (AuthCarrier::Auth(_), _) => a.auth,
184 (_, AuthCarrier::Auth(_)) => b.auth,
185 };
186
187 let frac = match (a.frac, b.frac) {
188 (FracCarrier::Invalid, _) => FracCarrier::Invalid,
190 (_, FracCarrier::Invalid) => FracCarrier::Invalid,
191 (
197 FracCarrier::Frac { owning: a_owning, dup: a_dup },
198 FracCarrier::Frac { owning: b_owning, dup: b_dup },
199 ) => {
200 let non_overlapping = {
201 &&& a_owning.dom().disjoint(b_dup.dom())
202 &&& b_owning.dom().disjoint(a_dup.dom())
203 &&& a_owning.dom().disjoint(b_owning.dom())
204 };
205 let aggreement = a_dup.agrees(b_dup);
206 if non_overlapping && aggreement {
207 FracCarrier::Frac {
208 owning: a_owning.union_prefer_right(b_owning),
209 dup: a_dup.union_prefer_right(b_dup),
210 }
211 } else {
212 FracCarrier::Invalid
213 }
214 },
215 };
216
217 MapCarrier { auth, frac }
218 }
219
220 proof fn valid_op(a: Self, b: Self) {
221 broadcast use lemma_submap_of_trans;
222
223 let ab = MapCarrier::op(a, b);
224 lemma_submap_of_op_frac(a, b);
225 if !a.frac.owning_map().dom().disjoint(a.frac.dup_map().dom()) {
227 lemma_set_disjoint_iff_empty_intersection(
229 a.frac.owning_map().dom(),
230 a.frac.dup_map().dom(),
231 );
232 let a_k = choose|k: K|
233 a.frac.owning_map().dom().intersect(a.frac.dup_map().dom()).contains(k);
234 assert(ab.frac.owning_map().dom().intersect(ab.frac.dup_map().dom()).contains(a_k)); };
236 }
237
238 proof fn commutative(a: Self, b: Self) {
239 let ab = Self::op(a, b);
240 let ba = Self::op(b, a);
241 assert(ab == ba);
242 }
243
244 proof fn associative(a: Self, b: Self, c: Self) {
245 let bc = Self::op(b, c);
246 let ab = Self::op(a, b);
247 let a_bc = Self::op(a, bc);
248 let ab_c = Self::op(ab, c);
249 assert(a_bc == ab_c);
250 }
251}
252
253impl<K, V> PCM for MapCarrier<K, V> {
254 closed spec fn unit() -> Self {
255 MapCarrier {
256 auth: AuthCarrier::Frac,
257 frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
258 }
259 }
260
261 proof fn op_unit(self) {
262 let x = Self::op(self, Self::unit());
263 assert(self == x);
264 }
265
266 proof fn unit_valid() {
267 }
268}
269
270proof fn lemma_submap_of_op_frac<K, V>(a: MapCarrier<K, V>, b: MapCarrier<K, V>)
271 requires
272 MapCarrier::op(a, b).valid(),
273 ensures
274 a.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
275 a.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
276 b.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
277 b.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
278{
279 let ab = MapCarrier::op(a, b);
280 assert(ab.frac.owning_map() == a.frac.owning_map().union_prefer_right(b.frac.owning_map()));
281 assert(ab.frac.dup_map() == a.frac.dup_map().union_prefer_right(b.frac.dup_map()));
282 assert(a.frac.owning_map().dom().disjoint(b.frac.owning_map().dom()));
283}
284
285broadcast proof fn lemma_submap_of_op<K, V>(a: MapCarrier<K, V>, b: MapCarrier<K, V>)
286 requires
287 #[trigger] MapCarrier::op(a, b).valid(),
288 ensures
289 a.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
290 a.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
291 a.auth.map() <= MapCarrier::op(a, b).auth.map(),
292 b.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
293 b.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
294 b.auth.map() <= MapCarrier::op(a, b).auth.map(),
295 a.valid(),
296 b.valid(),
297{
298 lemma_submap_of_op_frac(a, b);
299 MapCarrier::valid_op(a, b);
300 MapCarrier::commutative(a, b);
301 MapCarrier::valid_op(b, a);
302 let ab = MapCarrier::op(a, b);
303 assert(ab.auth.map() == a.auth.map().union_prefer_right(b.auth.map()));
304}
305
306#[verifier::reject_recursive_types(K)]
308pub tracked struct GhostMapAuth<K, V> {
309 r: Resource<MapCarrier<K, V>>,
310}
311
312#[verifier::reject_recursive_types(K)]
319pub tracked struct GhostSubmap<K, V> {
320 r: Resource<MapCarrier<K, V>>,
321}
322
323#[verifier::reject_recursive_types(K)]
329pub tracked struct GhostPersistentSubmap<K, V> {
330 r: Resource<MapCarrier<K, V>>,
331}
332
333#[verifier::reject_recursive_types(K)]
340pub tracked struct GhostPointsTo<K, V> {
341 submap: GhostSubmap<K, V>,
342}
343
344#[verifier::reject_recursive_types(K)]
350pub tracked struct GhostPersistentPointsTo<K, V> {
351 submap: GhostPersistentSubmap<K, V>,
352}
353
354impl<K, V> GhostMapAuth<K, V> {
355 #[verifier::type_invariant]
356 spec fn inv(self) -> bool {
357 &&& self.r.value().auth is Auth
358 &&& self.r.value().frac == FracCarrier::Frac {
359 owning: Map::<K, V>::empty(),
360 dup: Map::<K, V>::empty(),
361 }
362 }
363
364 pub closed spec fn id(self) -> Loc {
366 self.r.loc()
367 }
368
369 pub closed spec fn view(self) -> Map<K, V> {
371 self.r.value().auth.map()
372 }
373
374 pub open spec fn dom(self) -> Set<K> {
376 self@.dom()
377 }
378
379 pub open spec fn spec_index(self, key: K) -> V
381 recommends
382 self.dom().contains(key),
383 {
384 self@[key]
385 }
386
387 pub proof fn dummy() -> (tracked result: GhostMapAuth<K, V>) {
389 let tracked (auth, submap) = GhostMapAuth::<K, V>::new(Map::empty());
390 auth
391 }
392
393 pub proof fn take(tracked &mut self) -> (tracked result: GhostMapAuth<K, V>)
395 ensures
396 result == *old(self),
397 {
398 use_type_invariant(&*self);
399 let tracked mut r = Self::dummy();
400 tracked_swap(self, &mut r);
401 r
402 }
403
404 pub proof fn empty(tracked &self) -> (tracked result: GhostSubmap<K, V>)
406 ensures
407 result.id() == self.id(),
408 result@ == Map::<K, V>::empty(),
409 {
410 use_type_invariant(self);
411 let tracked r = Resource::<MapCarrier<_, _>>::create_unit(self.r.loc());
412 GhostSubmap { r }
413 }
414
415 pub proof fn insert_map(tracked &mut self, m: Map<K, V>) -> (tracked result: GhostSubmap<K, V>)
430 requires
431 old(self)@.dom().disjoint(m.dom()),
432 ensures
433 final(self).id() == old(self).id(),
434 final(self)@ == old(self)@.union_prefer_right(m),
435 result.id() == final(self).id(),
436 result@ == m,
437 {
438 broadcast use lemma_submap_of_trans;
439 broadcast use lemma_submap_of_op;
440
441 let tracked mut mself = Self::dummy();
442 tracked_swap(self, &mut mself);
443
444 use_type_invariant(&mself);
445 assert(mself.inv());
446 let tracked mut self_r = mself.r;
447
448 let full_carrier = MapCarrier {
449 auth: AuthCarrier::Auth(self_r.value().auth.map().union_prefer_right(m)),
450 frac: FracCarrier::Frac { owning: m, dup: Map::empty() },
451 };
452
453 assert(full_carrier.valid());
454 assert forall|c: MapCarrier<K, V>| #[trigger]
455 MapCarrier::op(self_r.value(), c).valid() implies MapCarrier::op(
456 full_carrier,
457 c,
458 ).valid() by {
459 assert(full_carrier.frac.owning_map().dom().disjoint(c.frac.dup_map().dom()));
460 }
461 let tracked updated_r = self_r.update(full_carrier);
462
463 let auth_carrier = MapCarrier {
464 auth: updated_r.value().auth,
465 frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
466 };
467 let frac_carrier = MapCarrier { auth: AuthCarrier::Frac, frac: updated_r.value().frac };
468
469 assert(updated_r.value() == MapCarrier::op(auth_carrier, frac_carrier));
470 let tracked (auth_r, frac_r) = updated_r.split(auth_carrier, frac_carrier);
471 self.r = auth_r;
472 GhostSubmap { r: frac_r }
473 }
474
475 pub proof fn insert(tracked &mut self, k: K, v: V) -> (tracked result: GhostPointsTo<K, V>)
488 requires
489 !old(self)@.contains_key(k),
490 ensures
491 final(self).id() == old(self).id(),
492 final(self)@ == old(self)@.insert(k, v),
493 result.id() == final(self).id(),
494 result@ == (k, v),
495 {
496 let tracked submap = self.insert_map(map![k => v]);
497 GhostPointsTo { submap }
498 }
499
500 pub proof fn delete(tracked &mut self, tracked submap: GhostSubmap<K, V>)
515 requires
516 submap.id() == old(self).id(),
517 ensures
518 final(self).id() == old(self).id(),
519 final(self)@ == old(self)@.remove_keys(submap@.dom()),
520 {
521 broadcast use lemma_submap_of_trans;
522 broadcast use lemma_submap_of_op;
523
524 use_type_invariant(&*self);
525 use_type_invariant(&submap);
526
527 let tracked mut mself = Self::dummy();
528 tracked_swap(self, &mut mself);
529 let tracked mut self_r = mself.r;
530
531 self_r = self_r.join(submap.r);
533
534 let auth_map = self_r.value().auth.map();
536 let new_auth_map = auth_map.remove_keys(submap@.dom());
537
538 let new_r = MapCarrier {
539 auth: AuthCarrier::Auth(new_auth_map),
540 frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
541 };
542
543 self.r = self_r.update(new_r);
545 }
546
547 pub proof fn delete_points_to(tracked &mut self, tracked p: GhostPointsTo<K, V>)
561 requires
562 p.id() == old(self).id(),
563 ensures
564 final(self).id() == old(self).id(),
565 final(self)@ == old(self)@.remove(p.key()),
566 {
567 use_type_invariant(&p);
568 p.lemma_map_view();
569 self.delete(p.submap);
570 }
571
572 pub proof fn new(m: Map<K, V>) -> (tracked result: (GhostMapAuth<K, V>, GhostSubmap<K, V>))
584 ensures
585 result.0.id() == result.1.id(),
586 result.0@ == m,
587 result.1@ == m,
588 {
589 let tracked full_r = Resource::alloc(
590 MapCarrier {
591 auth: AuthCarrier::Auth(m),
592 frac: FracCarrier::Frac { owning: m, dup: Map::empty() },
593 },
594 );
595
596 let auth_carrier = MapCarrier {
597 auth: AuthCarrier::Auth(m),
598 frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
599 };
600
601 let frac_carrier = MapCarrier {
602 auth: AuthCarrier::Frac,
603 frac: FracCarrier::Frac { owning: m, dup: Map::empty() },
604 };
605
606 assert(full_r.value() == MapCarrier::op(auth_carrier, frac_carrier));
607 let tracked (auth_r, frac_r) = full_r.split(auth_carrier, frac_carrier);
608 (GhostMapAuth { r: auth_r }, GhostSubmap { r: frac_r })
609 }
610}
611
612impl<K, V> GhostSubmap<K, V> {
613 #[verifier::type_invariant]
614 spec fn inv(self) -> bool {
615 &&& self.r.value().auth is Frac
616 &&& self.r.value().frac is Frac
617 &&& self.r.value().frac.dup_map().is_empty()
618 }
619
620 pub open spec fn is_points_to(self) -> bool {
623 &&& self@.len() == 1
624 &&& !self@.is_empty()
625 }
626
627 pub closed spec fn id(self) -> Loc {
629 self.r.loc()
630 }
631
632 pub closed spec fn view(self) -> Map<K, V> {
634 self.r.value().frac.owning_map()
635 }
636
637 pub open spec fn dom(self) -> Set<K> {
639 self@.dom()
640 }
641
642 pub open spec fn spec_index(self, key: K) -> V
644 recommends
645 self.dom().contains(key),
646 {
647 self@[key]
648 }
649
650 pub proof fn dummy() -> (tracked result: GhostSubmap<K, V>) {
652 let tracked (auth, submap) = GhostMapAuth::<K, V>::new(Map::empty());
653 submap
654 }
655
656 pub proof fn empty(tracked &self) -> (tracked result: GhostSubmap<K, V>)
658 ensures
659 result.id() == self.id(),
660 result@ == Map::<K, V>::empty(),
661 {
662 use_type_invariant(self);
663 let tracked r = Resource::<MapCarrier<_, _>>::create_unit(self.r.loc());
664 GhostSubmap { r }
665 }
666
667 pub proof fn take(tracked &mut self) -> (tracked result: GhostSubmap<K, V>)
669 ensures
670 old(self).id() == final(self).id(),
671 final(self)@.is_empty(),
672 result == *old(self),
673 result.id() == final(self).id(),
674 {
675 use_type_invariant(&*self);
676
677 let tracked mut r = self.empty();
678 tracked_swap(self, &mut r);
679 r
680 }
681
682 pub proof fn agree(tracked self: &GhostSubmap<K, V>, tracked auth: &GhostMapAuth<K, V>)
702 requires
703 self.id() == auth.id(),
704 ensures
705 self@ <= auth@,
706 {
707 broadcast use lemma_submap_of_trans;
708
709 use_type_invariant(self);
710 use_type_invariant(auth);
711
712 let tracked joined = self.r.join_shared(&auth.r);
713 joined.validate();
714 assert(self.r.value().frac.owning_map() <= joined.value().frac.owning_map());
715 }
716
717 pub proof fn combine(tracked &mut self, tracked other: GhostSubmap<K, V>)
721 requires
722 old(self).id() == other.id(),
723 ensures
724 final(self).id() == old(self).id(),
725 final(self)@ == old(self)@.union_prefer_right(other@),
726 old(self)@.dom().disjoint(other@.dom()),
727 {
728 use_type_invariant(&*self);
729 use_type_invariant(&other);
730
731 self.r.validate_2(&other.r);
732 incorporate(&mut self.r, other.r);
733 }
734
735 pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPointsTo<K, V>)
738 requires
739 old(self).id() == other.id(),
740 ensures
741 final(self).id() == old(self).id(),
742 final(self)@ == old(self)@.insert(other.key(), other.value()),
743 !old(self)@.contains_key(other.key()),
744 {
745 use_type_invariant(&*self);
746 use_type_invariant(&other);
747
748 other.lemma_map_view();
749 self.combine(other.submap);
750 }
751
752 pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubmap<K, V>)
754 requires
755 old(self).id() == other.id(),
756 ensures
757 final(self).id() == old(self).id(),
758 final(self)@ == old(self)@,
759 final(self)@.dom().disjoint(other@.dom()),
760 {
761 use_type_invariant(&*self);
762 use_type_invariant(other);
763 self.r.validate_2(&other.r);
764 }
765
766 pub proof fn disjoint_persistent(tracked &mut self, tracked other: &GhostPersistentSubmap<K, V>)
769 requires
770 old(self).id() == other.id(),
771 ensures
772 final(self).id() == old(self).id(),
773 final(self)@ == old(self)@,
774 final(self)@.dom().disjoint(other@.dom()),
775 {
776 use_type_invariant(&*self);
777 use_type_invariant(other);
778 self.r.validate_2(&other.r);
779 }
780
781 pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
784 requires
785 old(self).id() == other.id(),
786 ensures
787 final(self).id() == old(self).id(),
788 final(self)@ == old(self)@,
789 !final(self)@.contains_key(other.key()),
790 {
791 use_type_invariant(&*self);
792 use_type_invariant(other);
793 self.disjoint(&other.submap);
794 }
795
796 pub proof fn disjoint_persistent_points_to(
799 tracked &mut self,
800 tracked other: &GhostPersistentPointsTo<K, V>,
801 )
802 requires
803 old(self).id() == other.id(),
804 ensures
805 final(self).id() == old(self).id(),
806 final(self)@ == old(self)@,
807 !final(self)@.contains_key(other.key()),
808 {
809 use_type_invariant(&*self);
810 use_type_invariant(other);
811 self.disjoint_persistent(&other.submap);
812 }
813
814 pub proof fn split(tracked &mut self, s: Set<K>) -> (tracked result: GhostSubmap<K, V>)
816 requires
817 s <= old(self)@.dom(),
818 ensures
819 final(self).id() == old(self).id(),
820 result.id() == final(self).id(),
821 old(self)@ == final(self)@.union_prefer_right(result@),
822 result@.dom() =~= s,
823 final(self)@.dom() =~= old(self)@.dom() - s,
824 {
825 use_type_invariant(&*self);
826
827 let self_carrier = MapCarrier {
828 auth: AuthCarrier::Frac,
829 frac: FracCarrier::Frac {
830 owning: self.r.value().frac.owning_map().remove_keys(s),
831 dup: self.r.value().frac.dup_map(),
832 },
833 };
834
835 let res_carrier = MapCarrier {
836 auth: AuthCarrier::Frac,
837 frac: FracCarrier::Frac {
838 owning: self.r.value().frac.owning_map().restrict(s),
839 dup: self.r.value().frac.dup_map(),
840 },
841 };
842
843 assert(self.r.value().frac == MapCarrier::op(self_carrier, res_carrier).frac);
844 let tracked r = split_mut(&mut self.r, self_carrier, res_carrier);
845 GhostSubmap { r }
846 }
847
848 pub proof fn split_with_olddom(tracked &mut self, s: Set<K>, olddom: Set<K>) -> (tracked result:
849 GhostSubmap<K, V>)
850 requires
851 olddom == old(self)@.dom(),
852 s <= olddom,
853 ensures
854 final(self).id() == old(self).id(),
855 result.id() == final(self).id(),
856 old(self)@ == final(self)@.union_prefer_right(result@),
857 result@.dom() == s,
858 final(self)@.dom() == olddom - s,
859 {
860 let tracked out = self.split(s);
861 assert(olddom == old(self)@.dom());
862 assert(self@.dom() == old(self)@.dom() - s);
863 assert(self@.dom() == olddom - s);
864 assert(out@.dom() == s);
865 out
866 }
867
868 pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result: GhostPointsTo<K, V>)
870 requires
871 old(self)@.contains_key(k),
872 ensures
873 final(self).id() == old(self).id(),
874 result.id() == final(self).id(),
875 old(self)@ == final(self)@.insert(result.key(), result.value()),
876 result.key() == k,
877 final(self)@ == old(self)@.remove(k),
878 {
879 use_type_invariant(&*self);
880
881 let tracked submap = self.split(set![k]);
882 GhostPointsTo { submap }
883 }
884
885 pub proof fn update(tracked &mut self, tracked auth: &mut GhostMapAuth<K, V>, m: Map<K, V>)
904 requires
905 m.dom() <= old(self)@.dom(),
906 old(self).id() == old(auth).id(),
907 ensures
908 final(self).id() == old(self).id(),
909 final(auth).id() == old(auth).id(),
910 final(self)@ == old(self)@.union_prefer_right(m),
911 final(auth)@ == old(auth)@.union_prefer_right(m),
912 {
913 broadcast use lemma_submap_of_trans;
914 broadcast use lemma_submap_of_op;
915
916 use_type_invariant(&*self);
917 use_type_invariant(&*auth);
918
919 let tracked mut mself = Self::dummy();
920 tracked_swap(self, &mut mself);
921 let tracked mut frac_r = mself.r;
922
923 let tracked mut mauth = GhostMapAuth::<K, V>::dummy();
924 tracked_swap(auth, &mut mauth);
925 let tracked mut auth_r = mauth.r;
926
927 frac_r.validate_2(&auth_r);
928 let tracked mut full_r = frac_r.join(auth_r);
929
930 assert(full_r.value().frac.owning_map() == frac_r.value().frac.owning_map());
931
932 let auth_carrier = AuthCarrier::Auth(full_r.value().auth.map().union_prefer_right(m));
933 let frac_carrier = FracCarrier::Frac {
934 owning: full_r.value().frac.owning_map().union_prefer_right(m),
935 dup: Map::empty(),
936 };
937 let new_full_carrier = MapCarrier { auth: auth_carrier, frac: frac_carrier };
938
939 assert(new_full_carrier.valid());
940 let tracked r_upd = full_r.update(new_full_carrier);
941
942 let new_auth_carrier = MapCarrier {
943 auth: r_upd.value().auth,
944 frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
945 };
946 let new_frac_carrier = MapCarrier { auth: AuthCarrier::Frac, frac: r_upd.value().frac };
947 assert(r_upd.value().frac == MapCarrier::op(new_auth_carrier, new_frac_carrier).frac);
948 assert(r_upd.value() == MapCarrier::op(new_auth_carrier, new_frac_carrier));
949
950 let tracked (new_auth_r, new_frac_r) = r_upd.split(new_auth_carrier, new_frac_carrier);
951 auth.r = new_auth_r;
952 self.r = new_frac_r;
953 }
954
955 pub proof fn points_to(tracked self) -> (tracked r: GhostPointsTo<K, V>)
957 requires
958 self.is_points_to(),
959 ensures
960 self@ == map![r.key() => r.value()],
961 self.id() == r.id(),
962 {
963 let tracked r = GhostPointsTo { submap: self };
964 r.lemma_map_view();
965 r
966 }
967
968 pub proof fn persist(tracked self) -> (tracked r: GhostPersistentSubmap<K, V>)
970 ensures
971 self@ == r@,
972 self.id() == r.id(),
973 {
974 broadcast use lemma_submap_of_trans;
975 broadcast use lemma_submap_of_op;
976
977 use_type_invariant(&self);
978
979 let tracked mut r = self.r;
980
981 let self_carrier = MapCarrier {
982 auth: AuthCarrier::Frac,
983 frac: FracCarrier::Frac {
984 owning: self.r.value().frac.owning_map(),
985 dup: self.r.value().frac.dup_map(),
986 },
987 };
988
989 let res_carrier = MapCarrier {
990 auth: AuthCarrier::Frac,
991 frac: FracCarrier::Frac {
992 owning: self.r.value().frac.dup_map(),
993 dup: self.r.value().frac.owning_map(),
994 },
995 };
996
997 let tracked r = r.update(res_carrier);
998 GhostPersistentSubmap { r }
999 }
1000}
1001
1002impl<K, V> GhostPersistentSubmap<K, V> {
1003 #[verifier::type_invariant]
1004 spec fn inv(self) -> bool {
1005 &&& self.r.value().auth is Frac
1006 &&& self.r.value().frac is Frac
1007 &&& self.r.value().frac.owning_map().is_empty()
1008 }
1009
1010 pub open spec fn is_points_to(self) -> bool {
1013 &&& self@.len() == 1
1014 &&& !self@.is_empty()
1015 }
1016
1017 pub closed spec fn id(self) -> Loc {
1019 self.r.loc()
1020 }
1021
1022 pub closed spec fn view(self) -> Map<K, V> {
1024 self.r.value().frac.dup_map()
1025 }
1026
1027 pub open spec fn dom(self) -> Set<K> {
1029 self@.dom()
1030 }
1031
1032 pub open spec fn spec_index(self, key: K) -> V
1034 recommends
1035 self.dom().contains(key),
1036 {
1037 self@[key]
1038 }
1039
1040 pub proof fn dummy() -> (tracked result: GhostPersistentSubmap<K, V>) {
1042 let tracked owned = GhostSubmap::<K, V>::dummy();
1043 owned.persist()
1044 }
1045
1046 pub proof fn empty(tracked &self) -> (tracked result: GhostPersistentSubmap<K, V>)
1048 ensures
1049 result.id() == self.id(),
1050 result@ == Map::<K, V>::empty(),
1051 {
1052 use_type_invariant(self);
1053 let tracked r = Resource::<MapCarrier<_, _>>::create_unit(self.r.loc());
1054 GhostSubmap { r }.persist()
1055 }
1056
1057 pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentSubmap<K, V>)
1059 ensures
1060 result.id() == self.id(),
1061 result@ == self@,
1062 {
1063 use_type_invariant(&*self);
1064
1065 assert(MapCarrier::op(self.r.value(), self.r.value()) == self.r.value());
1066 let tracked r = super::super::lib::duplicate(&self.r);
1067
1068 GhostPersistentSubmap { r }
1069 }
1070
1071 pub proof fn agree(
1091 tracked self: &GhostPersistentSubmap<K, V>,
1092 tracked auth: &GhostMapAuth<K, V>,
1093 )
1094 requires
1095 self.id() == auth.id(),
1096 ensures
1097 self@ <= auth@,
1098 {
1099 broadcast use lemma_submap_of_trans;
1100
1101 use_type_invariant(self);
1102 use_type_invariant(auth);
1103
1104 let tracked joined = self.r.join_shared(&auth.r);
1105 joined.validate();
1106 assert(self.r.value().frac.dup_map() <= joined.value().frac.dup_map());
1107 }
1108
1109 pub proof fn combine(tracked &mut self, tracked other: GhostPersistentSubmap<K, V>)
1113 requires
1114 old(self).id() == other.id(),
1115 ensures
1116 final(self).id() == old(self).id(),
1117 final(self)@ == old(self)@.union_prefer_right(other@),
1118 old(self)@.agrees(other@),
1119 {
1120 use_type_invariant(&*self);
1121 use_type_invariant(&other);
1122
1123 self.r.validate_2(&other.r);
1124 incorporate(&mut self.r, other.r);
1125 }
1126
1127 pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPersistentPointsTo<K, V>)
1130 requires
1131 old(self).id() == other.id(),
1132 ensures
1133 final(self).id() == old(self).id(),
1134 final(self)@ == old(self)@.insert(other.key(), other.value()),
1135 old(self)@.contains_key(other.key()) ==> old(self)@[other.key()] == other.value(),
1136 {
1137 use_type_invariant(&*self);
1138 use_type_invariant(&other);
1139
1140 other.lemma_map_view();
1141 self.combine(other.submap);
1142 }
1143
1144 pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1146 requires
1147 old(self).id() == other.id(),
1148 ensures
1149 final(self).id() == old(self).id(),
1150 final(self)@ == old(self)@,
1151 final(self)@.dom().disjoint(other@.dom()),
1152 {
1153 use_type_invariant(&*self);
1154 use_type_invariant(other);
1155 self.r.validate_2(&other.r);
1156 }
1157
1158 pub proof fn intersection_agrees(tracked &mut self, tracked other: &GhostPersistentSubmap<K, V>)
1160 requires
1161 old(self).id() == other.id(),
1162 ensures
1163 final(self).id() == old(self).id(),
1164 final(self)@ == old(self)@,
1165 final(self)@.agrees(other@),
1166 {
1167 use_type_invariant(&*self);
1168 use_type_invariant(other);
1169 self.r.validate_2(&other.r);
1170 }
1171
1172 pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1175 requires
1176 old(self).id() == other.id(),
1177 ensures
1178 final(self).id() == old(self).id(),
1179 final(self)@ == old(self)@,
1180 !final(self)@.contains_key(other.key()),
1181 {
1182 use_type_invariant(&*self);
1183 use_type_invariant(other);
1184 self.disjoint(&other.submap);
1185 }
1186
1187 pub proof fn intersection_agrees_points_to(
1191 tracked &mut self,
1192 tracked other: &GhostPersistentPointsTo<K, V>,
1193 )
1194 requires
1195 old(self).id() == other.id(),
1196 ensures
1197 final(self).id() == old(self).id(),
1198 final(self)@ == old(self)@,
1199 final(self)@.contains_key(other.key()) ==> final(self)@[other.key()] == other.value(),
1200 {
1201 use_type_invariant(&*self);
1202 use_type_invariant(other);
1203 self.intersection_agrees(&other.submap);
1204 }
1205
1206 pub proof fn split(tracked &mut self, s: Set<K>) -> (tracked result: GhostPersistentSubmap<
1208 K,
1209 V,
1210 >)
1211 requires
1212 s <= old(self)@.dom(),
1213 ensures
1214 final(self).id() == old(self).id(),
1215 result.id() == final(self).id(),
1216 old(self)@ == final(self)@.union_prefer_right(result@),
1217 result@.dom() =~= s,
1218 final(self)@.dom() =~= old(self)@.dom() - s,
1219 {
1220 use_type_invariant(&*self);
1221
1222 let tracked mut r = Resource::alloc(MapCarrier::<K, V>::unit());
1223 tracked_swap(&mut self.r, &mut r);
1224
1225 let self_carrier = MapCarrier {
1226 auth: AuthCarrier::Frac,
1227 frac: FracCarrier::Frac {
1228 owning: r.value().frac.owning_map(),
1229 dup: r.value().frac.dup_map().remove_keys(s),
1230 },
1231 };
1232
1233 let res_carrier = MapCarrier {
1234 auth: AuthCarrier::Frac,
1235 frac: FracCarrier::Frac {
1236 owning: r.value().frac.owning_map(),
1237 dup: r.value().frac.dup_map().restrict(s),
1238 },
1239 };
1240
1241 assert(r.value().frac == MapCarrier::op(self_carrier, res_carrier).frac);
1242 let tracked (self_r, res_r) = r.split(self_carrier, res_carrier);
1243 self.r = self_r;
1244 GhostPersistentSubmap { r: res_r }
1245 }
1246
1247 pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result:
1249 GhostPersistentPointsTo<K, V>)
1250 requires
1251 old(self)@.contains_key(k),
1252 ensures
1253 final(self).id() == old(self).id(),
1254 result.id() == final(self).id(),
1255 old(self)@ == final(self)@.insert(result.key(), result.value()),
1256 result.key() == k,
1257 final(self)@ == old(self)@.remove(k),
1258 {
1259 use_type_invariant(&*self);
1260
1261 let tracked submap = self.split(set![k]);
1262 GhostPersistentPointsTo { submap }
1263 }
1264
1265 pub proof fn points_to(tracked self) -> (tracked r: GhostPersistentPointsTo<K, V>)
1267 requires
1268 self.is_points_to(),
1269 ensures
1270 self@ == map![r.key() => r.value()],
1271 self.id() == r.id(),
1272 {
1273 let tracked r = GhostPersistentPointsTo { submap: self };
1274 r.lemma_map_view();
1275 r
1276 }
1277}
1278
1279impl<K, V> GhostPointsTo<K, V> {
1280 #[verifier::type_invariant]
1281 spec fn inv(self) -> bool {
1282 self.submap.is_points_to()
1283 }
1284
1285 pub closed spec fn id(self) -> Loc {
1287 self.submap.id()
1288 }
1289
1290 pub open spec fn view(self) -> (K, V) {
1292 (self.key(), self.value())
1293 }
1294
1295 pub closed spec fn key(self) -> K {
1297 self.submap.dom().choose()
1298 }
1299
1300 pub closed spec fn value(self) -> V {
1302 self.submap[self.key()]
1303 }
1304
1305 pub proof fn agree(tracked self: &GhostPointsTo<K, V>, tracked auth: &GhostMapAuth<K, V>)
1323 requires
1324 self.id() == auth.id(),
1325 ensures
1326 auth@.contains_pair(self.key(), self.value()),
1327 {
1328 use_type_invariant(self);
1329 use_type_invariant(auth);
1330
1331 self.lemma_map_view();
1332 self.submap.agree(auth);
1333 assert(self.submap@ <= auth@);
1334 assert(self.submap@.dom().contains(self.key()));
1335 assert(auth@.dom().contains(self.key()));
1336 assert(self.submap@[self.key()] == self.value());
1337 assert(auth@[self.key()] == self.value());
1338 }
1339
1340 pub proof fn combine(tracked self, tracked other: GhostPointsTo<K, V>) -> (tracked r:
1343 GhostSubmap<K, V>)
1344 requires
1345 self.id() == other.id(),
1346 ensures
1347 r.id() == self.id(),
1348 r@ == map![self.key() => self.value(), other.key() => other.value()],
1349 self.key() != other.key(),
1350 {
1351 use_type_invariant(&self);
1352 use_type_invariant(&other);
1353
1354 let tracked mut submap = self.submap();
1355 submap.combine_points_to(other);
1356
1357 submap
1358 }
1359
1360 pub proof fn disjoint(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1362 requires
1363 old(self).id() == other.id(),
1364 ensures
1365 final(self).id() == old(self).id(),
1366 final(self)@ == old(self)@,
1367 final(self).key() != other.key(),
1368 {
1369 use_type_invariant(&*self);
1370 use_type_invariant(other);
1371 self.submap.disjoint(&other.submap);
1372 }
1373
1374 pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1376 requires
1377 old(self).id() == other.id(),
1378 ensures
1379 final(self).id() == old(self).id(),
1380 final(self)@ == old(self)@,
1381 !other.dom().contains(final(self).key()),
1382 {
1383 use_type_invariant(&*self);
1384 use_type_invariant(other);
1385 self.submap.disjoint(other);
1386 }
1387
1388 pub proof fn disjoint_persistent_submap(
1390 tracked &mut self,
1391 tracked other: &GhostPersistentSubmap<K, V>,
1392 )
1393 requires
1394 old(self).id() == other.id(),
1395 ensures
1396 final(self).id() == old(self).id(),
1397 final(self)@ == old(self)@,
1398 !other.dom().contains(final(self).key()),
1399 {
1400 use_type_invariant(&*self);
1401 use_type_invariant(other);
1402 self.submap.disjoint_persistent(other);
1403 }
1404
1405 pub proof fn disjoint_persistent(
1407 tracked &mut self,
1408 tracked other: &GhostPersistentPointsTo<K, V>,
1409 )
1410 requires
1411 old(self).id() == other.id(),
1412 ensures
1413 final(self).id() == old(self).id(),
1414 final(self)@ == old(self)@,
1415 final(self).key() != other.key(),
1416 {
1417 use_type_invariant(&*self);
1418 use_type_invariant(other);
1419 self.submap.disjoint_persistent_points_to(other);
1420 }
1421
1422 pub proof fn update(tracked &mut self, tracked auth: &mut GhostMapAuth<K, V>, v: V)
1424 requires
1425 old(self).id() == old(auth).id(),
1426 ensures
1427 final(self).id() == old(self).id(),
1428 final(auth).id() == old(auth).id(),
1429 final(self).key() == old(self).key(),
1430 final(self)@ == (final(self).key(), v),
1431 final(auth)@ == old(auth)@.union_prefer_right(map![final(self).key() => v]),
1432 {
1433 broadcast use lemma_submap_of_trans;
1434 broadcast use lemma_submap_of_op;
1435
1436 use_type_invariant(&*self);
1437 use_type_invariant(&*auth);
1438
1439 let ghost old_dom = self.submap.dom();
1440 self.lemma_map_view();
1441 let m = map![self.key() => v];
1442 assert(self.submap@.union_prefer_right(m) == m);
1443 self.submap.update(auth, m);
1444 }
1445
1446 pub proof fn submap(tracked self) -> (tracked r: GhostSubmap<K, V>)
1448 ensures
1449 r.id() == self.id(),
1450 r@ == map![self.key() => self.value()],
1451 {
1452 self.lemma_map_view();
1453 self.submap
1454 }
1455
1456 proof fn lemma_map_view(tracked &self)
1457 ensures
1458 self.submap@ == map![self.key() => self.value()],
1459 {
1460 use_type_invariant(self);
1461 let key = self.key();
1462 let target_dom = set![key];
1463
1464 assert(self.submap@.dom().len() == 1);
1465 assert(target_dom.len() == 1);
1466
1467 assert(self.submap@.dom().contains(key));
1468 assert(target_dom.contains(key));
1469
1470 assert(self.submap@.dom().remove(key).len() == 0);
1471 assert(target_dom.remove(key).len() == 0);
1472
1473 assert(self.submap@.dom() =~= target_dom);
1474 assert(self.submap@ == map![self.key() => self.value()]);
1475 }
1476
1477 pub proof fn lemma_view(self)
1479 ensures
1480 self@ == (self.key(), self.value()),
1481 {
1482 }
1483
1484 pub proof fn persist(tracked self) -> (tracked r: GhostPersistentPointsTo<K, V>)
1486 ensures
1487 self@ == r@,
1488 self.id() == r.id(),
1489 {
1490 use_type_invariant(&self);
1491 self.submap.persist().points_to()
1492 }
1493}
1494
1495impl<K, V> GhostPersistentPointsTo<K, V> {
1496 #[verifier::type_invariant]
1497 spec fn inv(self) -> bool {
1498 self.submap.is_points_to()
1499 }
1500
1501 pub closed spec fn id(self) -> Loc {
1503 self.submap.id()
1504 }
1505
1506 pub open spec fn view(self) -> (K, V) {
1508 (self.key(), self.value())
1509 }
1510
1511 pub closed spec fn key(self) -> K {
1513 self.submap.dom().choose()
1514 }
1515
1516 pub closed spec fn value(self) -> V {
1518 self.submap[self.key()]
1519 }
1520
1521 pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentPointsTo<K, V>)
1523 ensures
1524 result.id() == self.id(),
1525 result@ == self@,
1526 {
1527 use_type_invariant(&*self);
1528 let tracked submap = self.submap.duplicate();
1529 GhostPersistentPointsTo { submap }
1530 }
1531
1532 pub proof fn agree(
1550 tracked self: &GhostPersistentPointsTo<K, V>,
1551 tracked auth: &GhostMapAuth<K, V>,
1552 )
1553 requires
1554 self.id() == auth.id(),
1555 ensures
1556 auth@.contains_pair(self.key(), self.value()),
1557 {
1558 use_type_invariant(self);
1559 use_type_invariant(auth);
1560
1561 self.lemma_map_view();
1562 self.submap.agree(auth);
1563 assert(self.submap@ <= auth@);
1564 assert(self.submap@.contains_key(self.key()));
1565 }
1566
1567 pub proof fn combine(
1569 tracked self,
1570 tracked other: GhostPersistentPointsTo<K, V>,
1571 ) -> (tracked submap: GhostPersistentSubmap<K, V>)
1572 requires
1573 self.id() == other.id(),
1574 ensures
1575 submap.id() == self.id(),
1576 submap@ == map![self.key() => self.value(), other.key() => other.value()],
1577 self.key() != other.key() ==> submap@.len() == 2,
1578 self.key() == other.key() ==> submap@.len() == 1,
1579 {
1580 use_type_invariant(&self);
1581 use_type_invariant(&other);
1582
1583 let tracked mut submap = self.submap();
1584 submap.combine_points_to(other);
1585
1586 submap
1587 }
1588
1589 pub proof fn disjoint(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1592 requires
1593 old(self).id() == other.id(),
1594 ensures
1595 final(self).id() == old(self).id(),
1596 final(self)@ == old(self)@,
1597 final(self).key() != other.key(),
1598 {
1599 use_type_invariant(&*self);
1600 use_type_invariant(other);
1601 self.disjoint_submap(&other.submap);
1602 }
1603
1604 pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1607 requires
1608 old(self).id() == other.id(),
1609 ensures
1610 final(self).id() == old(self).id(),
1611 final(self)@ == old(self)@,
1612 !other@.contains_key(final(self).key()),
1613 {
1614 use_type_invariant(&*self);
1615 use_type_invariant(other);
1616 self.submap.disjoint(&other);
1617 }
1618
1619 pub proof fn intersection_agrees(
1622 tracked &mut self,
1623 tracked other: &GhostPersistentPointsTo<K, V>,
1624 )
1625 requires
1626 old(self).id() == other.id(),
1627 ensures
1628 final(self).id() == old(self).id(),
1629 final(self)@ == old(self)@,
1630 final(self).key() == other.key() ==> final(self).value() == other.value(),
1631 {
1632 use_type_invariant(&*self);
1633 use_type_invariant(other);
1634 self.submap.intersection_agrees_points_to(&other);
1635 }
1636
1637 pub proof fn intersection_agrees_submap(
1639 tracked &mut self,
1640 tracked other: &GhostPersistentSubmap<K, V>,
1641 )
1642 requires
1643 old(self).id() == other.id(),
1644 ensures
1645 final(self).id() == old(self).id(),
1646 final(self)@ == old(self)@,
1647 other@.contains_key(final(self).key()) ==> other@[final(self).key()]
1648 == final(self).value(),
1649 {
1650 use_type_invariant(&*self);
1651 use_type_invariant(other);
1652 self.submap.intersection_agrees(other);
1653 }
1654
1655 pub proof fn submap(tracked self) -> (tracked r: GhostPersistentSubmap<K, V>)
1657 ensures
1658 r.id() == self.id(),
1659 r@ == map![self.key() => self.value()],
1660 {
1661 self.lemma_map_view();
1662 self.submap
1663 }
1664
1665 proof fn lemma_map_view(tracked &self)
1666 ensures
1667 self.submap@ == map![self.key() => self.value()],
1668 {
1669 use_type_invariant(self);
1670 let key = self.key();
1671 let target_dom = set![key];
1672
1673 assert(self.submap@.dom().len() == 1);
1674 assert(target_dom.len() == 1);
1675
1676 assert(self.submap@.dom().contains(key));
1677 assert(target_dom.contains(key));
1678
1679 assert(self.submap@.dom().remove(key).len() == 0);
1680 assert(target_dom.remove(key).len() == 0);
1681
1682 assert(self.submap@.dom() =~= target_dom);
1683 assert(self.submap@ == map![self.key() => self.value()]);
1684 }
1685
1686 pub proof fn lemma_view(self)
1688 ensures
1689 self@ == (self.key(), self.value()),
1690 {
1691 }
1692}
1693
1694}