1use super::super::imap::*;
77use super::super::imap_lib::*;
78use super::super::iset_lib::*;
79use super::super::modes::*;
80use super::super::prelude::*;
81use super::Loc;
82use super::algebra::ResourceAlgebra;
83#[cfg(verus_keep_ghost)]
84use super::incorporate;
85use super::pcm::PCM;
86use super::pcm::Resource;
87#[cfg(verus_keep_ghost)]
88use super::split_mut;
89
90verus! {
91
92broadcast use {super::super::group_vstd_default, super::super::imap::group_imap_lemmas};
93
94#[verifier::reject_recursive_types(K)]
95#[verifier::ext_equal]
96enum AuthCarrier<K, V> {
97 Auth(IMap<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: IMap<K, V>, dup: IMap<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) -> IMap<K, V>
115 recommends
116 self.valid(),
117 {
118 match self {
119 AuthCarrier::Auth(m) => m,
120 AuthCarrier::Frac => IMap::empty(),
121 AuthCarrier::Invalid => IMap::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) -> IMap<K, V> {
135 match self {
136 FracCarrier::Frac { owning, .. } => owning,
137 FracCarrier::Invalid => IMap::empty(),
138 }
139 }
140
141 spec fn dup_map(self) -> IMap<K, V> {
142 match self {
143 FracCarrier::Frac { dup, .. } => dup,
144 FracCarrier::Invalid => IMap::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_iset_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: IMap::empty(), dup: IMap::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: IMap::<K, V>::empty(),
360 dup: IMap::<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) -> IMap<K, V> {
371 self.r.value().auth.map()
372 }
373
374 pub open spec fn dom(self) -> ISet<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(IMap::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@ == IMap::<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: IMap<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: IMap::empty() },
451 };
452
453 assert(full_carrier.valid());
454 let tracked updated_r = self_r.update(full_carrier);
455
456 let auth_carrier = MapCarrier {
457 auth: updated_r.value().auth,
458 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
459 };
460 let frac_carrier = MapCarrier { auth: AuthCarrier::Frac, frac: updated_r.value().frac };
461
462 assert(updated_r.value() == MapCarrier::op(auth_carrier, frac_carrier));
463 let tracked (auth_r, frac_r) = updated_r.split(auth_carrier, frac_carrier);
464 self.r = auth_r;
465 GhostSubmap { r: frac_r }
466 }
467
468 pub proof fn insert(tracked &mut self, k: K, v: V) -> (tracked result: GhostPointsTo<K, V>)
481 requires
482 !old(self)@.contains_key(k),
483 ensures
484 final(self).id() == old(self).id(),
485 final(self)@ == old(self)@.insert(k, v),
486 result.id() == final(self).id(),
487 result@ == (k, v),
488 {
489 let tracked submap = self.insert_map(imap![k => v]);
490 GhostPointsTo { submap }
491 }
492
493 pub proof fn delete(tracked &mut self, tracked submap: GhostSubmap<K, V>)
508 requires
509 submap.id() == old(self).id(),
510 ensures
511 final(self).id() == old(self).id(),
512 final(self)@ == old(self)@.remove_keys(submap@.dom()),
513 {
514 broadcast use lemma_submap_of_trans;
515 broadcast use lemma_submap_of_op;
516
517 use_type_invariant(&*self);
518 use_type_invariant(&submap);
519
520 let tracked mut mself = Self::dummy();
521 tracked_swap(self, &mut mself);
522 let tracked mut self_r = mself.r;
523
524 self_r = self_r.join(submap.r);
526
527 let auth_map = self_r.value().auth.map();
529 let new_auth_map = auth_map.remove_keys(submap@.dom());
530
531 let new_r = MapCarrier {
532 auth: AuthCarrier::Auth(new_auth_map),
533 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
534 };
535
536 self.r = self_r.update(new_r);
538 }
539
540 pub proof fn delete_points_to(tracked &mut self, tracked p: GhostPointsTo<K, V>)
554 requires
555 p.id() == old(self).id(),
556 ensures
557 final(self).id() == old(self).id(),
558 final(self)@ == old(self)@.remove(p.key()),
559 {
560 use_type_invariant(&p);
561 p.lemma_map_view();
562 self.delete(p.submap);
563 }
564
565 pub proof fn new(m: IMap<K, V>) -> (tracked result: (GhostMapAuth<K, V>, GhostSubmap<K, V>))
577 ensures
578 result.0.id() == result.1.id(),
579 result.0@ == m,
580 result.1@ == m,
581 {
582 let tracked full_r = Resource::alloc(
583 MapCarrier {
584 auth: AuthCarrier::Auth(m),
585 frac: FracCarrier::Frac { owning: m, dup: IMap::empty() },
586 },
587 );
588
589 let auth_carrier = MapCarrier {
590 auth: AuthCarrier::Auth(m),
591 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
592 };
593
594 let frac_carrier = MapCarrier {
595 auth: AuthCarrier::Frac,
596 frac: FracCarrier::Frac { owning: m, dup: IMap::empty() },
597 };
598
599 assert(full_r.value() == MapCarrier::op(auth_carrier, frac_carrier));
600 let tracked (auth_r, frac_r) = full_r.split(auth_carrier, frac_carrier);
601 (GhostMapAuth { r: auth_r }, GhostSubmap { r: frac_r })
602 }
603}
604
605impl<K, V> GhostSubmap<K, V> {
606 #[verifier::type_invariant]
607 spec fn inv(self) -> bool {
608 &&& self.r.value().auth is Frac
609 &&& self.r.value().frac is Frac
610 &&& self.r.value().frac.dup_map().is_empty()
611 }
612
613 pub open spec fn is_points_to(self) -> bool {
616 &&& self@.len() == 1
617 &&& self.dom().finite()
618 &&& !self@.is_empty()
619 }
620
621 pub closed spec fn id(self) -> Loc {
623 self.r.loc()
624 }
625
626 pub closed spec fn view(self) -> IMap<K, V> {
628 self.r.value().frac.owning_map()
629 }
630
631 pub open spec fn dom(self) -> ISet<K> {
633 self@.dom()
634 }
635
636 pub open spec fn spec_index(self, key: K) -> V
638 recommends
639 self.dom().contains(key),
640 {
641 self@[key]
642 }
643
644 pub proof fn dummy() -> (tracked result: GhostSubmap<K, V>) {
646 let tracked (auth, submap) = GhostMapAuth::<K, V>::new(IMap::empty());
647 submap
648 }
649
650 pub proof fn empty(tracked &self) -> (tracked result: GhostSubmap<K, V>)
652 ensures
653 result.id() == self.id(),
654 result@ == IMap::<K, V>::empty(),
655 {
656 use_type_invariant(self);
657 let tracked r = Resource::<MapCarrier<_, _>>::create_unit(self.r.loc());
658 GhostSubmap { r }
659 }
660
661 pub proof fn take(tracked &mut self) -> (tracked result: GhostSubmap<K, V>)
663 ensures
664 old(self).id() == final(self).id(),
665 final(self)@.is_empty(),
666 result == *old(self),
667 result.id() == final(self).id(),
668 {
669 use_type_invariant(&*self);
670
671 let tracked mut r = self.empty();
672 tracked_swap(self, &mut r);
673 r
674 }
675
676 pub proof fn agree(tracked self: &GhostSubmap<K, V>, tracked auth: &GhostMapAuth<K, V>)
696 requires
697 self.id() == auth.id(),
698 ensures
699 self@ <= auth@,
700 {
701 broadcast use lemma_submap_of_trans;
702
703 use_type_invariant(self);
704 use_type_invariant(auth);
705
706 let tracked joined = self.r.join_shared(&auth.r);
707 joined.validate();
708 assert(self.r.value().frac.owning_map() <= joined.value().frac.owning_map());
709 }
710
711 pub proof fn combine(tracked &mut self, tracked other: GhostSubmap<K, V>)
715 requires
716 old(self).id() == other.id(),
717 ensures
718 final(self).id() == old(self).id(),
719 final(self)@ == old(self)@.union_prefer_right(other@),
720 old(self)@.dom().disjoint(other@.dom()),
721 {
722 use_type_invariant(&*self);
723 use_type_invariant(&other);
724
725 self.r.validate_2(&other.r);
726 incorporate(&mut self.r, other.r);
727 }
728
729 pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPointsTo<K, V>)
732 requires
733 old(self).id() == other.id(),
734 ensures
735 final(self).id() == old(self).id(),
736 final(self)@ == old(self)@.insert(other.key(), other.value()),
737 !old(self)@.contains_key(other.key()),
738 {
739 use_type_invariant(&*self);
740 use_type_invariant(&other);
741
742 other.lemma_map_view();
743 self.combine(other.submap);
744 }
745
746 pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubmap<K, V>)
748 requires
749 old(self).id() == other.id(),
750 ensures
751 final(self).id() == old(self).id(),
752 final(self)@ == old(self)@,
753 final(self)@.dom().disjoint(other@.dom()),
754 {
755 use_type_invariant(&*self);
756 use_type_invariant(other);
757 self.r.validate_2(&other.r);
758 }
759
760 pub proof fn disjoint_persistent(tracked &mut self, tracked other: &GhostPersistentSubmap<K, V>)
763 requires
764 old(self).id() == other.id(),
765 ensures
766 final(self).id() == old(self).id(),
767 final(self)@ == old(self)@,
768 final(self)@.dom().disjoint(other@.dom()),
769 {
770 use_type_invariant(&*self);
771 use_type_invariant(other);
772 self.r.validate_2(&other.r);
773 }
774
775 pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
778 requires
779 old(self).id() == other.id(),
780 ensures
781 final(self).id() == old(self).id(),
782 final(self)@ == old(self)@,
783 !final(self)@.contains_key(other.key()),
784 {
785 use_type_invariant(&*self);
786 use_type_invariant(other);
787 self.disjoint(&other.submap);
788 }
789
790 pub proof fn disjoint_persistent_points_to(
793 tracked &mut self,
794 tracked other: &GhostPersistentPointsTo<K, V>,
795 )
796 requires
797 old(self).id() == other.id(),
798 ensures
799 final(self).id() == old(self).id(),
800 final(self)@ == old(self)@,
801 !final(self)@.contains_key(other.key()),
802 {
803 use_type_invariant(&*self);
804 use_type_invariant(other);
805 self.disjoint_persistent(&other.submap);
806 }
807
808 pub proof fn split(tracked &mut self, s: ISet<K>) -> (tracked result: GhostSubmap<K, V>)
810 requires
811 s <= old(self)@.dom(),
812 ensures
813 final(self).id() == old(self).id(),
814 result.id() == final(self).id(),
815 old(self)@ == final(self)@.union_prefer_right(result@),
816 result@.dom() =~= s,
817 final(self)@.dom() =~= old(self)@.dom() - s,
818 {
819 use_type_invariant(&*self);
820
821 let self_carrier = MapCarrier {
822 auth: AuthCarrier::Frac,
823 frac: FracCarrier::Frac {
824 owning: self.r.value().frac.owning_map().remove_keys(s),
825 dup: self.r.value().frac.dup_map(),
826 },
827 };
828
829 let res_carrier = MapCarrier {
830 auth: AuthCarrier::Frac,
831 frac: FracCarrier::Frac {
832 owning: self.r.value().frac.owning_map().restrict(s),
833 dup: self.r.value().frac.dup_map(),
834 },
835 };
836
837 assert(self.r.value().frac == MapCarrier::op(self_carrier, res_carrier).frac);
838 let tracked r = split_mut(&mut self.r, self_carrier, res_carrier);
839 GhostSubmap { r }
840 }
841
842 pub proof fn split_with_olddom(
843 tracked &mut self,
844 s: ISet<K>,
845 olddom: ISet<K>,
846 ) -> (tracked result: GhostSubmap<K, V>)
847 requires
848 olddom == old(self)@.dom(),
849 s <= olddom,
850 ensures
851 final(self).id() == old(self).id(),
852 result.id() == final(self).id(),
853 old(self)@ == final(self)@.union_prefer_right(result@),
854 result@.dom() == s,
855 final(self)@.dom() == olddom - s,
856 {
857 let tracked out = self.split(s);
858 assert(olddom == old(self)@.dom());
859 assert(self@.dom() == old(self)@.dom() - s);
860 assert(self@.dom() == olddom - s);
861 assert(out@.dom() == s);
862 out
863 }
864
865 pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result: GhostPointsTo<K, V>)
867 requires
868 old(self)@.contains_key(k),
869 ensures
870 final(self).id() == old(self).id(),
871 result.id() == final(self).id(),
872 old(self)@ == final(self)@.insert(result.key(), result.value()),
873 result.key() == k,
874 final(self)@ == old(self)@.remove(k),
875 {
876 use_type_invariant(&*self);
877
878 let tracked submap = self.split(iset![k]);
879 GhostPointsTo { submap }
880 }
881
882 pub proof fn update(tracked &mut self, tracked auth: &mut GhostMapAuth<K, V>, m: IMap<K, V>)
901 requires
902 m.dom() <= old(self)@.dom(),
903 old(self).id() == old(auth).id(),
904 ensures
905 final(self).id() == old(self).id(),
906 final(auth).id() == old(auth).id(),
907 final(self)@ == old(self)@.union_prefer_right(m),
908 final(auth)@ == old(auth)@.union_prefer_right(m),
909 {
910 broadcast use lemma_submap_of_trans;
911 broadcast use lemma_submap_of_op;
912
913 use_type_invariant(&*self);
914 use_type_invariant(&*auth);
915
916 let tracked mut mself = Self::dummy();
917 tracked_swap(self, &mut mself);
918 let tracked mut frac_r = mself.r;
919
920 let tracked mut mauth = GhostMapAuth::<K, V>::dummy();
921 tracked_swap(auth, &mut mauth);
922 let tracked mut auth_r = mauth.r;
923
924 frac_r.validate_2(&auth_r);
925 let tracked mut full_r = frac_r.join(auth_r);
926
927 assert(full_r.value().frac.owning_map() == frac_r.value().frac.owning_map());
928
929 let auth_carrier = AuthCarrier::Auth(full_r.value().auth.map().union_prefer_right(m));
930 let frac_carrier = FracCarrier::Frac {
931 owning: full_r.value().frac.owning_map().union_prefer_right(m),
932 dup: IMap::empty(),
933 };
934 let new_full_carrier = MapCarrier { auth: auth_carrier, frac: frac_carrier };
935
936 assert(new_full_carrier.valid());
937 let tracked r_upd = full_r.update(new_full_carrier);
938
939 let new_auth_carrier = MapCarrier {
940 auth: r_upd.value().auth,
941 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
942 };
943 let new_frac_carrier = MapCarrier { auth: AuthCarrier::Frac, frac: r_upd.value().frac };
944 assert(r_upd.value().frac == MapCarrier::op(new_auth_carrier, new_frac_carrier).frac);
945 assert(r_upd.value() == MapCarrier::op(new_auth_carrier, new_frac_carrier));
946
947 let tracked (new_auth_r, new_frac_r) = r_upd.split(new_auth_carrier, new_frac_carrier);
948 auth.r = new_auth_r;
949 self.r = new_frac_r;
950 }
951
952 pub proof fn points_to(tracked self) -> (tracked r: GhostPointsTo<K, V>)
954 requires
955 self.is_points_to(),
956 ensures
957 self@ == imap![r.key() => r.value()],
958 self.id() == r.id(),
959 {
960 let tracked r = GhostPointsTo { submap: self };
961 r.lemma_map_view();
962 r
963 }
964
965 pub proof fn persist(tracked self) -> (tracked r: GhostPersistentSubmap<K, V>)
967 ensures
968 self@ == r@,
969 self.id() == r.id(),
970 {
971 broadcast use lemma_submap_of_trans;
972 broadcast use lemma_submap_of_op;
973
974 use_type_invariant(&self);
975
976 let tracked mut r = self.r;
977
978 let self_carrier = MapCarrier {
979 auth: AuthCarrier::Frac,
980 frac: FracCarrier::Frac {
981 owning: self.r.value().frac.owning_map(),
982 dup: self.r.value().frac.dup_map(),
983 },
984 };
985
986 let res_carrier = MapCarrier {
987 auth: AuthCarrier::Frac,
988 frac: FracCarrier::Frac {
989 owning: self.r.value().frac.dup_map(),
990 dup: self.r.value().frac.owning_map(),
991 },
992 };
993
994 let tracked r = r.update(res_carrier);
995 GhostPersistentSubmap { r }
996 }
997}
998
999impl<K, V> GhostPersistentSubmap<K, V> {
1000 #[verifier::type_invariant]
1001 spec fn inv(self) -> bool {
1002 &&& self.r.value().auth is Frac
1003 &&& self.r.value().frac is Frac
1004 &&& self.r.value().frac.owning_map().is_empty()
1005 }
1006
1007 pub open spec fn is_points_to(self) -> bool {
1010 &&& self@.len() == 1
1011 &&& self.dom().finite()
1012 &&& !self@.is_empty()
1013 }
1014
1015 pub closed spec fn id(self) -> Loc {
1017 self.r.loc()
1018 }
1019
1020 pub closed spec fn view(self) -> IMap<K, V> {
1022 self.r.value().frac.dup_map()
1023 }
1024
1025 pub open spec fn dom(self) -> ISet<K> {
1027 self@.dom()
1028 }
1029
1030 pub open spec fn spec_index(self, key: K) -> V
1032 recommends
1033 self.dom().contains(key),
1034 {
1035 self@[key]
1036 }
1037
1038 pub proof fn dummy() -> (tracked result: GhostPersistentSubmap<K, V>) {
1040 let tracked owned = GhostSubmap::<K, V>::dummy();
1041 owned.persist()
1042 }
1043
1044 pub proof fn empty(tracked &self) -> (tracked result: GhostPersistentSubmap<K, V>)
1046 ensures
1047 result.id() == self.id(),
1048 result@ == IMap::<K, V>::empty(),
1049 {
1050 use_type_invariant(self);
1051 let tracked r = Resource::<MapCarrier<_, _>>::create_unit(self.r.loc());
1052 GhostSubmap { r }.persist()
1053 }
1054
1055 pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentSubmap<K, V>)
1057 ensures
1058 result.id() == self.id(),
1059 result@ == self@,
1060 {
1061 use_type_invariant(&*self);
1062
1063 assert(MapCarrier::op(self.r.value(), self.r.value()) == self.r.value());
1064 let tracked r = super::lib::duplicate(&self.r);
1065
1066 GhostPersistentSubmap { r }
1067 }
1068
1069 pub proof fn agree(
1089 tracked self: &GhostPersistentSubmap<K, V>,
1090 tracked auth: &GhostMapAuth<K, V>,
1091 )
1092 requires
1093 self.id() == auth.id(),
1094 ensures
1095 self@ <= auth@,
1096 {
1097 broadcast use lemma_submap_of_trans;
1098
1099 use_type_invariant(self);
1100 use_type_invariant(auth);
1101
1102 let tracked joined = self.r.join_shared(&auth.r);
1103 joined.validate();
1104 assert(self.r.value().frac.dup_map() <= joined.value().frac.dup_map());
1105 }
1106
1107 pub proof fn combine(tracked &mut self, tracked other: GhostPersistentSubmap<K, V>)
1111 requires
1112 old(self).id() == other.id(),
1113 ensures
1114 final(self).id() == old(self).id(),
1115 final(self)@ == old(self)@.union_prefer_right(other@),
1116 old(self)@.agrees(other@),
1117 {
1118 use_type_invariant(&*self);
1119 use_type_invariant(&other);
1120
1121 self.r.validate_2(&other.r);
1122 incorporate(&mut self.r, other.r);
1123 }
1124
1125 pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPersistentPointsTo<K, V>)
1128 requires
1129 old(self).id() == other.id(),
1130 ensures
1131 final(self).id() == old(self).id(),
1132 final(self)@ == old(self)@.insert(other.key(), other.value()),
1133 old(self)@.contains_key(other.key()) ==> old(self)@[other.key()] == other.value(),
1134 {
1135 use_type_invariant(&*self);
1136 use_type_invariant(&other);
1137
1138 other.lemma_map_view();
1139 self.combine(other.submap);
1140 }
1141
1142 pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1144 requires
1145 old(self).id() == other.id(),
1146 ensures
1147 final(self).id() == old(self).id(),
1148 final(self)@ == old(self)@,
1149 final(self)@.dom().disjoint(other@.dom()),
1150 {
1151 use_type_invariant(&*self);
1152 use_type_invariant(other);
1153 self.r.validate_2(&other.r);
1154 }
1155
1156 pub proof fn intersection_agrees(tracked &mut self, tracked other: &GhostPersistentSubmap<K, V>)
1158 requires
1159 old(self).id() == other.id(),
1160 ensures
1161 final(self).id() == old(self).id(),
1162 final(self)@ == old(self)@,
1163 final(self)@.agrees(other@),
1164 {
1165 use_type_invariant(&*self);
1166 use_type_invariant(other);
1167 self.r.validate_2(&other.r);
1168 }
1169
1170 pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1173 requires
1174 old(self).id() == other.id(),
1175 ensures
1176 final(self).id() == old(self).id(),
1177 final(self)@ == old(self)@,
1178 !final(self)@.contains_key(other.key()),
1179 {
1180 use_type_invariant(&*self);
1181 use_type_invariant(other);
1182 self.disjoint(&other.submap);
1183 }
1184
1185 pub proof fn intersection_agrees_points_to(
1189 tracked &mut self,
1190 tracked other: &GhostPersistentPointsTo<K, V>,
1191 )
1192 requires
1193 old(self).id() == other.id(),
1194 ensures
1195 final(self).id() == old(self).id(),
1196 final(self)@ == old(self)@,
1197 final(self)@.contains_key(other.key()) ==> final(self)@[other.key()] == other.value(),
1198 {
1199 use_type_invariant(&*self);
1200 use_type_invariant(other);
1201 self.intersection_agrees(&other.submap);
1202 }
1203
1204 pub proof fn split(tracked &mut self, s: ISet<K>) -> (tracked result: GhostPersistentSubmap<
1206 K,
1207 V,
1208 >)
1209 requires
1210 s <= old(self)@.dom(),
1211 ensures
1212 final(self).id() == old(self).id(),
1213 result.id() == final(self).id(),
1214 old(self)@ == final(self)@.union_prefer_right(result@),
1215 result@.dom() =~= s,
1216 final(self)@.dom() =~= old(self)@.dom() - s,
1217 {
1218 use_type_invariant(&*self);
1219
1220 let tracked mut r = Resource::alloc(MapCarrier::<K, V>::unit());
1221 tracked_swap(&mut self.r, &mut r);
1222
1223 let self_carrier = MapCarrier {
1224 auth: AuthCarrier::Frac,
1225 frac: FracCarrier::Frac {
1226 owning: r.value().frac.owning_map(),
1227 dup: r.value().frac.dup_map().remove_keys(s),
1228 },
1229 };
1230
1231 let res_carrier = MapCarrier {
1232 auth: AuthCarrier::Frac,
1233 frac: FracCarrier::Frac {
1234 owning: r.value().frac.owning_map(),
1235 dup: r.value().frac.dup_map().restrict(s),
1236 },
1237 };
1238
1239 assert(r.value().frac == MapCarrier::op(self_carrier, res_carrier).frac);
1240 let tracked (self_r, res_r) = r.split(self_carrier, res_carrier);
1241 self.r = self_r;
1242 GhostPersistentSubmap { r: res_r }
1243 }
1244
1245 pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result:
1247 GhostPersistentPointsTo<K, V>)
1248 requires
1249 old(self)@.contains_key(k),
1250 ensures
1251 final(self).id() == old(self).id(),
1252 result.id() == final(self).id(),
1253 old(self)@ == final(self)@.insert(result.key(), result.value()),
1254 result.key() == k,
1255 final(self)@ == old(self)@.remove(k),
1256 {
1257 use_type_invariant(&*self);
1258
1259 let tracked submap = self.split(iset![k]);
1260 GhostPersistentPointsTo { submap }
1261 }
1262
1263 pub proof fn points_to(tracked self) -> (tracked r: GhostPersistentPointsTo<K, V>)
1265 requires
1266 self.is_points_to(),
1267 ensures
1268 self@ == imap![r.key() => r.value()],
1269 self.id() == r.id(),
1270 {
1271 let tracked r = GhostPersistentPointsTo { submap: self };
1272 r.lemma_map_view();
1273 r
1274 }
1275}
1276
1277impl<K, V> GhostPointsTo<K, V> {
1278 #[verifier::type_invariant]
1279 spec fn inv(self) -> bool {
1280 self.submap.is_points_to()
1281 }
1282
1283 pub closed spec fn id(self) -> Loc {
1285 self.submap.id()
1286 }
1287
1288 pub open spec fn view(self) -> (K, V) {
1290 (self.key(), self.value())
1291 }
1292
1293 pub closed spec fn key(self) -> K {
1295 self.submap.dom().choose()
1296 }
1297
1298 pub closed spec fn value(self) -> V {
1300 self.submap[self.key()]
1301 }
1302
1303 pub proof fn agree(tracked self: &GhostPointsTo<K, V>, tracked auth: &GhostMapAuth<K, V>)
1321 requires
1322 self.id() == auth.id(),
1323 ensures
1324 auth@.contains_pair(self.key(), self.value()),
1325 {
1326 use_type_invariant(self);
1327 use_type_invariant(auth);
1328
1329 self.lemma_map_view();
1330 self.submap.agree(auth);
1331 assert(self.submap@ <= auth@);
1332 assert(self.submap@.dom().contains(self.key()));
1333 assert(auth@.dom().contains(self.key()));
1334 assert(self.submap@[self.key()] == self.value());
1335 assert(auth@[self.key()] == self.value());
1336 }
1337
1338 pub proof fn combine(tracked self, tracked other: GhostPointsTo<K, V>) -> (tracked r:
1341 GhostSubmap<K, V>)
1342 requires
1343 self.id() == other.id(),
1344 ensures
1345 r.id() == self.id(),
1346 r@ == imap![self.key() => self.value(), other.key() => other.value()],
1347 self.key() != other.key(),
1348 {
1349 use_type_invariant(&self);
1350 use_type_invariant(&other);
1351
1352 let tracked mut submap = self.submap();
1353 submap.combine_points_to(other);
1354
1355 submap
1356 }
1357
1358 pub proof fn disjoint(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1360 requires
1361 old(self).id() == other.id(),
1362 ensures
1363 final(self).id() == old(self).id(),
1364 final(self)@ == old(self)@,
1365 final(self).key() != other.key(),
1366 {
1367 use_type_invariant(&*self);
1368 use_type_invariant(other);
1369 self.submap.disjoint(&other.submap);
1370 }
1371
1372 pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1374 requires
1375 old(self).id() == other.id(),
1376 ensures
1377 final(self).id() == old(self).id(),
1378 final(self)@ == old(self)@,
1379 !other.dom().contains(final(self).key()),
1380 {
1381 use_type_invariant(&*self);
1382 use_type_invariant(other);
1383 self.submap.disjoint(other);
1384 }
1385
1386 pub proof fn disjoint_persistent_submap(
1388 tracked &mut self,
1389 tracked other: &GhostPersistentSubmap<K, V>,
1390 )
1391 requires
1392 old(self).id() == other.id(),
1393 ensures
1394 final(self).id() == old(self).id(),
1395 final(self)@ == old(self)@,
1396 !other.dom().contains(final(self).key()),
1397 {
1398 use_type_invariant(&*self);
1399 use_type_invariant(other);
1400 self.submap.disjoint_persistent(other);
1401 }
1402
1403 pub proof fn disjoint_persistent(
1405 tracked &mut self,
1406 tracked other: &GhostPersistentPointsTo<K, V>,
1407 )
1408 requires
1409 old(self).id() == other.id(),
1410 ensures
1411 final(self).id() == old(self).id(),
1412 final(self)@ == old(self)@,
1413 final(self).key() != other.key(),
1414 {
1415 use_type_invariant(&*self);
1416 use_type_invariant(other);
1417 self.submap.disjoint_persistent_points_to(other);
1418 }
1419
1420 pub proof fn update(tracked &mut self, tracked auth: &mut GhostMapAuth<K, V>, v: V)
1422 requires
1423 old(self).id() == old(auth).id(),
1424 ensures
1425 final(self).id() == old(self).id(),
1426 final(auth).id() == old(auth).id(),
1427 final(self).key() == old(self).key(),
1428 final(self)@ == (final(self).key(), v),
1429 final(auth)@ == old(auth)@.union_prefer_right(imap![final(self).key() => v]),
1430 {
1431 broadcast use lemma_submap_of_trans;
1432 broadcast use lemma_submap_of_op;
1433
1434 use_type_invariant(&*self);
1435 use_type_invariant(&*auth);
1436
1437 let ghost old_dom = self.submap.dom();
1438 self.lemma_map_view();
1439 let m = imap![self.key() => v];
1440 assert(self.submap@.union_prefer_right(m) == m);
1441 self.submap.update(auth, m);
1442 }
1443
1444 pub proof fn submap(tracked self) -> (tracked r: GhostSubmap<K, V>)
1446 ensures
1447 r.id() == self.id(),
1448 r@ == imap![self.key() => self.value()],
1449 {
1450 self.lemma_map_view();
1451 self.submap
1452 }
1453
1454 proof fn lemma_map_view(tracked &self)
1455 ensures
1456 self.submap@ == imap![self.key() => self.value()],
1457 {
1458 use_type_invariant(self);
1459 let key = self.key();
1460 let target_dom = iset![key];
1461
1462 assert(self.submap@.dom().len() == 1);
1463 assert(target_dom.len() == 1);
1464
1465 assert(self.submap@.dom().finite());
1466 assert(target_dom.finite());
1467
1468 assert(self.submap@.dom().contains(key));
1469 assert(target_dom.contains(key));
1470
1471 assert(self.submap@.dom().remove(key).len() == 0);
1472 assert(target_dom.remove(key).len() == 0);
1473
1474 assert(self.submap@.dom() =~= target_dom);
1475 assert(self.submap@ == imap![self.key() => self.value()]);
1476 }
1477
1478 pub proof fn lemma_view(self)
1480 ensures
1481 self@ == (self.key(), self.value()),
1482 {
1483 }
1484
1485 pub proof fn persist(tracked self) -> (tracked r: GhostPersistentPointsTo<K, V>)
1487 ensures
1488 self@ == r@,
1489 self.id() == r.id(),
1490 {
1491 use_type_invariant(&self);
1492 self.submap.persist().points_to()
1493 }
1494}
1495
1496impl<K, V> GhostPersistentPointsTo<K, V> {
1497 #[verifier::type_invariant]
1498 spec fn inv(self) -> bool {
1499 self.submap.is_points_to()
1500 }
1501
1502 pub closed spec fn id(self) -> Loc {
1504 self.submap.id()
1505 }
1506
1507 pub open spec fn view(self) -> (K, V) {
1509 (self.key(), self.value())
1510 }
1511
1512 pub closed spec fn key(self) -> K {
1514 self.submap.dom().choose()
1515 }
1516
1517 pub closed spec fn value(self) -> V {
1519 self.submap[self.key()]
1520 }
1521
1522 pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentPointsTo<K, V>)
1524 ensures
1525 result.id() == self.id(),
1526 result@ == self@,
1527 {
1528 use_type_invariant(&*self);
1529 let tracked submap = self.submap.duplicate();
1530 GhostPersistentPointsTo { submap }
1531 }
1532
1533 pub proof fn agree(
1551 tracked self: &GhostPersistentPointsTo<K, V>,
1552 tracked auth: &GhostMapAuth<K, V>,
1553 )
1554 requires
1555 self.id() == auth.id(),
1556 ensures
1557 auth@.contains_pair(self.key(), self.value()),
1558 {
1559 use_type_invariant(self);
1560 use_type_invariant(auth);
1561
1562 self.lemma_map_view();
1563 self.submap.agree(auth);
1564 assert(self.submap@ <= auth@);
1565 assert(self.submap@.contains_key(self.key()));
1566 }
1567
1568 pub proof fn combine(
1570 tracked self,
1571 tracked other: GhostPersistentPointsTo<K, V>,
1572 ) -> (tracked submap: GhostPersistentSubmap<K, V>)
1573 requires
1574 self.id() == other.id(),
1575 ensures
1576 submap.id() == self.id(),
1577 submap@ == imap![self.key() => self.value(), other.key() => other.value()],
1578 self.key() != other.key() ==> submap@.len() == 2,
1579 self.key() == other.key() ==> submap@.len() == 1,
1580 {
1581 use_type_invariant(&self);
1582 use_type_invariant(&other);
1583
1584 let tracked mut submap = self.submap();
1585 submap.combine_points_to(other);
1586
1587 submap
1588 }
1589
1590 pub proof fn disjoint(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1593 requires
1594 old(self).id() == other.id(),
1595 ensures
1596 final(self).id() == old(self).id(),
1597 final(self)@ == old(self)@,
1598 final(self).key() != other.key(),
1599 {
1600 use_type_invariant(&*self);
1601 use_type_invariant(other);
1602 self.disjoint_submap(&other.submap);
1603 }
1604
1605 pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1608 requires
1609 old(self).id() == other.id(),
1610 ensures
1611 final(self).id() == old(self).id(),
1612 final(self)@ == old(self)@,
1613 !other@.contains_key(final(self).key()),
1614 {
1615 use_type_invariant(&*self);
1616 use_type_invariant(other);
1617 self.submap.disjoint(&other);
1618 }
1619
1620 pub proof fn intersection_agrees(
1623 tracked &mut self,
1624 tracked other: &GhostPersistentPointsTo<K, V>,
1625 )
1626 requires
1627 old(self).id() == other.id(),
1628 ensures
1629 final(self).id() == old(self).id(),
1630 final(self)@ == old(self)@,
1631 final(self).key() == other.key() ==> final(self).value() == other.value(),
1632 {
1633 use_type_invariant(&*self);
1634 use_type_invariant(other);
1635 self.submap.intersection_agrees_points_to(&other);
1636 }
1637
1638 pub proof fn intersection_agrees_submap(
1640 tracked &mut self,
1641 tracked other: &GhostPersistentSubmap<K, V>,
1642 )
1643 requires
1644 old(self).id() == other.id(),
1645 ensures
1646 final(self).id() == old(self).id(),
1647 final(self)@ == old(self)@,
1648 other@.contains_key(final(self).key()) ==> other@[final(self).key()]
1649 == final(self).value(),
1650 {
1651 use_type_invariant(&*self);
1652 use_type_invariant(other);
1653 self.submap.intersection_agrees(other);
1654 }
1655
1656 pub proof fn submap(tracked self) -> (tracked r: GhostPersistentSubmap<K, V>)
1658 ensures
1659 r.id() == self.id(),
1660 r@ == imap![self.key() => self.value()],
1661 {
1662 self.lemma_map_view();
1663 self.submap
1664 }
1665
1666 proof fn lemma_map_view(tracked &self)
1667 ensures
1668 self.submap@ == imap![self.key() => self.value()],
1669 {
1670 use_type_invariant(self);
1671 let key = self.key();
1672 let target_dom = iset![key];
1673
1674 assert(self.submap@.dom().len() == 1);
1675 assert(target_dom.len() == 1);
1676
1677 assert(self.submap@.dom().finite());
1678 assert(target_dom.finite());
1679
1680 assert(self.submap@.dom().contains(key));
1681 assert(target_dom.contains(key));
1682
1683 assert(self.submap@.dom().remove(key).len() == 0);
1684 assert(target_dom.remove(key).len() == 0);
1685
1686 assert(self.submap@.dom() =~= target_dom);
1687 assert(self.submap@ == imap![self.key() => self.value()]);
1688 }
1689
1690 pub proof fn lemma_view(self)
1692 ensures
1693 self@ == (self.key(), self.value()),
1694 {
1695 }
1696}
1697
1698}