1use super::super::super::imap::*;
77use super::super::super::imap_lib::*;
78use super::super::super::iset_lib::*;
79use super::super::super::modes::*;
80use super::super::super::prelude::*;
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 {
93 super::super::super::group_vstd_default,
94 super::super::super::imap::group_imap_lemmas,
95};
96
97#[verifier::reject_recursive_types(K)]
98#[verifier::ext_equal]
99enum AuthCarrier<K, V> {
100 Auth(IMap<K, V>),
101 Frac,
102 Invalid,
103}
104
105#[verifier::reject_recursive_types(K)]
106#[verifier::ext_equal]
107enum FracCarrier<K, V> {
108 Frac { owning: IMap<K, V>, dup: IMap<K, V> },
109 Invalid,
110}
111
112impl<K, V> AuthCarrier<K, V> {
113 spec fn valid(self) -> bool {
114 !(self is Invalid)
115 }
116
117 spec fn map(self) -> IMap<K, V>
118 recommends
119 self.valid(),
120 {
121 match self {
122 AuthCarrier::Auth(m) => m,
123 AuthCarrier::Frac => IMap::empty(),
124 AuthCarrier::Invalid => IMap::empty(),
125 }
126 }
127}
128
129impl<K, V> FracCarrier<K, V> {
130 spec fn valid(self) -> bool {
131 match self {
132 FracCarrier::Invalid => false,
133 FracCarrier::Frac { owning, dup } => owning.dom().disjoint(dup.dom()),
134 }
135 }
136
137 spec fn owning_map(self) -> IMap<K, V> {
138 match self {
139 FracCarrier::Frac { owning, .. } => owning,
140 FracCarrier::Invalid => IMap::empty(),
141 }
142 }
143
144 spec fn dup_map(self) -> IMap<K, V> {
145 match self {
146 FracCarrier::Frac { dup, .. } => dup,
147 FracCarrier::Invalid => IMap::empty(),
148 }
149 }
150}
151
152#[verifier::reject_recursive_types(K)]
153#[verifier::ext_equal]
154tracked struct IMapCarrier<K, V> {
156 auth: AuthCarrier<K, V>,
157 frac: FracCarrier<K, V>,
158}
159
160impl<K, V> ResourceAlgebra for IMapCarrier<K, V> {
161 closed spec fn valid(self) -> bool {
162 match (self.auth, self.frac) {
163 (AuthCarrier::Invalid, _) => false,
164 (_, FracCarrier::Invalid) => false,
165 (AuthCarrier::Auth(auth), FracCarrier::Frac { owning, dup }) => {
166 &&& owning <= auth
167 &&& dup <= auth
168 &&& owning.dom().disjoint(dup.dom())
169 },
170 (AuthCarrier::Frac, FracCarrier::Frac { owning, dup }) => owning.dom().disjoint(
171 dup.dom(),
172 ),
173 }
174 }
175
176 closed spec fn op(a: Self, b: Self) -> Self {
177 let auth = match (a.auth, b.auth) {
178 (AuthCarrier::Invalid, _) => AuthCarrier::Invalid,
180 (_, AuthCarrier::Invalid) => AuthCarrier::Invalid,
181 (AuthCarrier::Auth(_), AuthCarrier::Auth(_)) => AuthCarrier::Invalid,
183 (AuthCarrier::Frac, AuthCarrier::Frac) => AuthCarrier::Frac,
185 (AuthCarrier::Auth(_), _) => a.auth,
187 (_, AuthCarrier::Auth(_)) => b.auth,
188 };
189
190 let frac = match (a.frac, b.frac) {
191 (FracCarrier::Invalid, _) => FracCarrier::Invalid,
193 (_, FracCarrier::Invalid) => FracCarrier::Invalid,
194 (
200 FracCarrier::Frac { owning: a_owning, dup: a_dup },
201 FracCarrier::Frac { owning: b_owning, dup: b_dup },
202 ) => {
203 let non_overlapping = {
204 &&& a_owning.dom().disjoint(b_dup.dom())
205 &&& b_owning.dom().disjoint(a_dup.dom())
206 &&& a_owning.dom().disjoint(b_owning.dom())
207 };
208 let aggreement = a_dup.agrees(b_dup);
209 if non_overlapping && aggreement {
210 FracCarrier::Frac {
211 owning: a_owning.union_prefer_right(b_owning),
212 dup: a_dup.union_prefer_right(b_dup),
213 }
214 } else {
215 FracCarrier::Invalid
216 }
217 },
218 };
219
220 IMapCarrier { auth, frac }
221 }
222
223 proof fn valid_op(a: Self, b: Self) {
224 broadcast use lemma_submap_of_trans;
225
226 let ab = IMapCarrier::op(a, b);
227 lemma_submap_of_op_frac(a, b);
228 if !a.frac.owning_map().dom().disjoint(a.frac.dup_map().dom()) {
230 lemma_iset_disjoint_iff_empty_intersection(
232 a.frac.owning_map().dom(),
233 a.frac.dup_map().dom(),
234 );
235 let a_k = choose|k: K|
236 a.frac.owning_map().dom().intersect(a.frac.dup_map().dom()).contains(k);
237 assert(ab.frac.owning_map().dom().intersect(ab.frac.dup_map().dom()).contains(a_k)); };
239 }
240
241 proof fn commutative(a: Self, b: Self) {
242 let ab = Self::op(a, b);
243 let ba = Self::op(b, a);
244 assert(ab == ba);
245 }
246
247 proof fn associative(a: Self, b: Self, c: Self) {
248 let bc = Self::op(b, c);
249 let ab = Self::op(a, b);
250 let a_bc = Self::op(a, bc);
251 let ab_c = Self::op(ab, c);
252 assert(a_bc == ab_c);
253 }
254}
255
256impl<K, V> PCM for IMapCarrier<K, V> {
257 closed spec fn unit() -> Self {
258 IMapCarrier {
259 auth: AuthCarrier::Frac,
260 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
261 }
262 }
263
264 proof fn op_unit(self) {
265 let x = Self::op(self, Self::unit());
266 assert(self == x);
267 }
268
269 proof fn unit_valid() {
270 }
271}
272
273proof fn lemma_submap_of_op_frac<K, V>(a: IMapCarrier<K, V>, b: IMapCarrier<K, V>)
274 requires
275 IMapCarrier::op(a, b).valid(),
276 ensures
277 a.frac.owning_map() <= IMapCarrier::op(a, b).frac.owning_map(),
278 a.frac.dup_map() <= IMapCarrier::op(a, b).frac.dup_map(),
279 b.frac.owning_map() <= IMapCarrier::op(a, b).frac.owning_map(),
280 b.frac.dup_map() <= IMapCarrier::op(a, b).frac.dup_map(),
281{
282 let ab = IMapCarrier::op(a, b);
283 assert(ab.frac.owning_map() == a.frac.owning_map().union_prefer_right(b.frac.owning_map()));
284 assert(ab.frac.dup_map() == a.frac.dup_map().union_prefer_right(b.frac.dup_map()));
285 assert(a.frac.owning_map().dom().disjoint(b.frac.owning_map().dom()));
286}
287
288broadcast proof fn lemma_submap_of_op<K, V>(a: IMapCarrier<K, V>, b: IMapCarrier<K, V>)
289 requires
290 #[trigger] IMapCarrier::op(a, b).valid(),
291 ensures
292 a.frac.owning_map() <= IMapCarrier::op(a, b).frac.owning_map(),
293 a.frac.dup_map() <= IMapCarrier::op(a, b).frac.dup_map(),
294 a.auth.map() <= IMapCarrier::op(a, b).auth.map(),
295 b.frac.owning_map() <= IMapCarrier::op(a, b).frac.owning_map(),
296 b.frac.dup_map() <= IMapCarrier::op(a, b).frac.dup_map(),
297 b.auth.map() <= IMapCarrier::op(a, b).auth.map(),
298 a.valid(),
299 b.valid(),
300{
301 lemma_submap_of_op_frac(a, b);
302 IMapCarrier::valid_op(a, b);
303 IMapCarrier::commutative(a, b);
304 IMapCarrier::valid_op(b, a);
305 let ab = IMapCarrier::op(a, b);
306 assert(ab.auth.map() == a.auth.map().union_prefer_right(b.auth.map()));
307}
308
309#[verifier::reject_recursive_types(K)]
311pub tracked struct GhostIMapAuth<K, V> {
312 r: Resource<IMapCarrier<K, V>>,
313}
314
315#[verifier::reject_recursive_types(K)]
322pub tracked struct GhostISubmap<K, V> {
323 r: Resource<IMapCarrier<K, V>>,
324}
325
326#[verifier::reject_recursive_types(K)]
332pub tracked struct GhostPersistentISubmap<K, V> {
333 r: Resource<IMapCarrier<K, V>>,
334}
335
336#[verifier::reject_recursive_types(K)]
343pub tracked struct GhostIPointsTo<K, V> {
344 submap: GhostISubmap<K, V>,
345}
346
347#[verifier::reject_recursive_types(K)]
353pub tracked struct GhostPersistentIPointsTo<K, V> {
354 submap: GhostPersistentISubmap<K, V>,
355}
356
357impl<K, V> GhostIMapAuth<K, V> {
358 #[verifier::type_invariant]
359 spec fn inv(self) -> bool {
360 &&& self.r.value().auth is Auth
361 &&& self.r.value().frac == FracCarrier::Frac {
362 owning: IMap::<K, V>::empty(),
363 dup: IMap::<K, V>::empty(),
364 }
365 }
366
367 pub closed spec fn id(self) -> Loc {
369 self.r.loc()
370 }
371
372 pub closed spec fn view(self) -> IMap<K, V> {
374 self.r.value().auth.map()
375 }
376
377 pub open spec fn dom(self) -> ISet<K> {
379 self@.dom()
380 }
381
382 pub open spec fn spec_index(self, key: K) -> V
384 recommends
385 self.dom().contains(key),
386 {
387 self@[key]
388 }
389
390 pub proof fn dummy() -> (tracked result: GhostIMapAuth<K, V>) {
392 let tracked (auth, submap) = GhostIMapAuth::<K, V>::new(IMap::empty());
393 auth
394 }
395
396 pub proof fn take(tracked &mut self) -> (tracked result: GhostIMapAuth<K, V>)
398 ensures
399 result == *old(self),
400 {
401 use_type_invariant(&*self);
402 let tracked mut r = Self::dummy();
403 tracked_swap(self, &mut r);
404 r
405 }
406
407 pub proof fn empty(tracked &self) -> (tracked result: GhostISubmap<K, V>)
409 ensures
410 result.id() == self.id(),
411 result@ == IMap::<K, V>::empty(),
412 {
413 use_type_invariant(self);
414 let tracked r = Resource::<IMapCarrier<_, _>>::create_unit(self.r.loc());
415 GhostISubmap { r }
416 }
417
418 pub proof fn insert_map(tracked &mut self, m: IMap<K, V>) -> (tracked result: GhostISubmap<
433 K,
434 V,
435 >)
436 requires
437 old(self)@.dom().disjoint(m.dom()),
438 ensures
439 final(self).id() == old(self).id(),
440 final(self)@ == old(self)@.union_prefer_right(m),
441 result.id() == final(self).id(),
442 result@ == m,
443 {
444 broadcast use lemma_submap_of_trans;
445 broadcast use lemma_submap_of_op;
446
447 let tracked mut mself = Self::dummy();
448 tracked_swap(self, &mut mself);
449
450 use_type_invariant(&mself);
451 assert(mself.inv());
452 let tracked mut self_r = mself.r;
453
454 let full_carrier = IMapCarrier {
455 auth: AuthCarrier::Auth(self_r.value().auth.map().union_prefer_right(m)),
456 frac: FracCarrier::Frac { owning: m, dup: IMap::empty() },
457 };
458
459 assert(full_carrier.valid());
460 let tracked updated_r = self_r.update(full_carrier);
461
462 let auth_carrier = IMapCarrier {
463 auth: updated_r.value().auth,
464 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
465 };
466 let frac_carrier = IMapCarrier { auth: AuthCarrier::Frac, frac: updated_r.value().frac };
467
468 assert(updated_r.value() == IMapCarrier::op(auth_carrier, frac_carrier));
469 let tracked (auth_r, frac_r) = updated_r.split(auth_carrier, frac_carrier);
470 self.r = auth_r;
471 GhostISubmap { r: frac_r }
472 }
473
474 pub proof fn insert(tracked &mut self, k: K, v: V) -> (tracked result: GhostIPointsTo<K, V>)
487 requires
488 !old(self)@.contains_key(k),
489 ensures
490 final(self).id() == old(self).id(),
491 final(self)@ == old(self)@.insert(k, v),
492 result.id() == final(self).id(),
493 result@ == (k, v),
494 {
495 let tracked submap = self.insert_map(imap![k => v]);
496 GhostIPointsTo { submap }
497 }
498
499 pub proof fn delete(tracked &mut self, tracked submap: GhostISubmap<K, V>)
514 requires
515 submap.id() == old(self).id(),
516 ensures
517 final(self).id() == old(self).id(),
518 final(self)@ == old(self)@.remove_keys(submap@.dom()),
519 {
520 broadcast use lemma_submap_of_trans;
521 broadcast use lemma_submap_of_op;
522
523 use_type_invariant(&*self);
524 use_type_invariant(&submap);
525
526 let tracked mut mself = Self::dummy();
527 tracked_swap(self, &mut mself);
528 let tracked mut self_r = mself.r;
529
530 self_r = self_r.join(submap.r);
532
533 let auth_map = self_r.value().auth.map();
535 let new_auth_map = auth_map.remove_keys(submap@.dom());
536
537 let new_r = IMapCarrier {
538 auth: AuthCarrier::Auth(new_auth_map),
539 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
540 };
541
542 self.r = self_r.update(new_r);
544 }
545
546 pub proof fn delete_points_to(tracked &mut self, tracked p: GhostIPointsTo<K, V>)
560 requires
561 p.id() == old(self).id(),
562 ensures
563 final(self).id() == old(self).id(),
564 final(self)@ == old(self)@.remove(p.key()),
565 {
566 use_type_invariant(&p);
567 p.lemma_map_view();
568 self.delete(p.submap);
569 }
570
571 pub proof fn new(m: IMap<K, V>) -> (tracked result: (GhostIMapAuth<K, V>, GhostISubmap<K, V>))
583 ensures
584 result.0.id() == result.1.id(),
585 result.0@ == m,
586 result.1@ == m,
587 {
588 let tracked full_r = Resource::alloc(
589 IMapCarrier {
590 auth: AuthCarrier::Auth(m),
591 frac: FracCarrier::Frac { owning: m, dup: IMap::empty() },
592 },
593 );
594
595 let auth_carrier = IMapCarrier {
596 auth: AuthCarrier::Auth(m),
597 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
598 };
599
600 let frac_carrier = IMapCarrier {
601 auth: AuthCarrier::Frac,
602 frac: FracCarrier::Frac { owning: m, dup: IMap::empty() },
603 };
604
605 assert(full_r.value() == IMapCarrier::op(auth_carrier, frac_carrier));
606 let tracked (auth_r, frac_r) = full_r.split(auth_carrier, frac_carrier);
607 (GhostIMapAuth { r: auth_r }, GhostISubmap { r: frac_r })
608 }
609}
610
611impl<K, V> GhostISubmap<K, V> {
612 #[verifier::type_invariant]
613 spec fn inv(self) -> bool {
614 &&& self.r.value().auth is Frac
615 &&& self.r.value().frac is Frac
616 &&& self.r.value().frac.dup_map().is_empty()
617 }
618
619 pub open spec fn is_points_to(self) -> bool {
622 &&& self@.len() == 1
623 &&& self.dom().finite()
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) -> IMap<K, V> {
634 self.r.value().frac.owning_map()
635 }
636
637 pub open spec fn dom(self) -> ISet<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: GhostISubmap<K, V>) {
652 let tracked (auth, submap) = GhostIMapAuth::<K, V>::new(IMap::empty());
653 submap
654 }
655
656 pub proof fn empty(tracked &self) -> (tracked result: GhostISubmap<K, V>)
658 ensures
659 result.id() == self.id(),
660 result@ == IMap::<K, V>::empty(),
661 {
662 use_type_invariant(self);
663 let tracked r = Resource::<IMapCarrier<_, _>>::create_unit(self.r.loc());
664 GhostISubmap { r }
665 }
666
667 pub proof fn take(tracked &mut self) -> (tracked result: GhostISubmap<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: &GhostISubmap<K, V>, tracked auth: &GhostIMapAuth<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: GhostISubmap<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: GhostIPointsTo<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: &GhostISubmap<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(
769 tracked &mut self,
770 tracked other: &GhostPersistentISubmap<K, V>,
771 )
772 requires
773 old(self).id() == other.id(),
774 ensures
775 final(self).id() == old(self).id(),
776 final(self)@ == old(self)@,
777 final(self)@.dom().disjoint(other@.dom()),
778 {
779 use_type_invariant(&*self);
780 use_type_invariant(other);
781 self.r.validate_2(&other.r);
782 }
783
784 pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostIPointsTo<K, V>)
787 requires
788 old(self).id() == other.id(),
789 ensures
790 final(self).id() == old(self).id(),
791 final(self)@ == old(self)@,
792 !final(self)@.contains_key(other.key()),
793 {
794 use_type_invariant(&*self);
795 use_type_invariant(other);
796 self.disjoint(&other.submap);
797 }
798
799 pub proof fn disjoint_persistent_points_to(
802 tracked &mut self,
803 tracked other: &GhostPersistentIPointsTo<K, V>,
804 )
805 requires
806 old(self).id() == other.id(),
807 ensures
808 final(self).id() == old(self).id(),
809 final(self)@ == old(self)@,
810 !final(self)@.contains_key(other.key()),
811 {
812 use_type_invariant(&*self);
813 use_type_invariant(other);
814 self.disjoint_persistent(&other.submap);
815 }
816
817 pub proof fn split(tracked &mut self, s: ISet<K>) -> (tracked result: GhostISubmap<K, V>)
819 requires
820 s <= old(self)@.dom(),
821 ensures
822 final(self).id() == old(self).id(),
823 result.id() == final(self).id(),
824 old(self)@ == final(self)@.union_prefer_right(result@),
825 result@.dom() =~= s,
826 final(self)@.dom() =~= old(self)@.dom() - s,
827 {
828 use_type_invariant(&*self);
829
830 let self_carrier = IMapCarrier {
831 auth: AuthCarrier::Frac,
832 frac: FracCarrier::Frac {
833 owning: self.r.value().frac.owning_map().remove_keys(s),
834 dup: self.r.value().frac.dup_map(),
835 },
836 };
837
838 let res_carrier = IMapCarrier {
839 auth: AuthCarrier::Frac,
840 frac: FracCarrier::Frac {
841 owning: self.r.value().frac.owning_map().restrict(s),
842 dup: self.r.value().frac.dup_map(),
843 },
844 };
845
846 assert(self.r.value().frac == IMapCarrier::op(self_carrier, res_carrier).frac);
847 let tracked r = split_mut(&mut self.r, self_carrier, res_carrier);
848 GhostISubmap { r }
849 }
850
851 pub proof fn split_with_olddom(
852 tracked &mut self,
853 s: ISet<K>,
854 olddom: ISet<K>,
855 ) -> (tracked result: GhostISubmap<K, V>)
856 requires
857 olddom == old(self)@.dom(),
858 s <= olddom,
859 ensures
860 final(self).id() == old(self).id(),
861 result.id() == final(self).id(),
862 old(self)@ == final(self)@.union_prefer_right(result@),
863 result@.dom() == s,
864 final(self)@.dom() == olddom - s,
865 {
866 let tracked out = self.split(s);
867 assert(olddom == old(self)@.dom());
868 assert(self@.dom() == old(self)@.dom() - s);
869 assert(self@.dom() == olddom - s);
870 assert(out@.dom() == s);
871 out
872 }
873
874 pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result: GhostIPointsTo<K, V>)
876 requires
877 old(self)@.contains_key(k),
878 ensures
879 final(self).id() == old(self).id(),
880 result.id() == final(self).id(),
881 old(self)@ == final(self)@.insert(result.key(), result.value()),
882 result.key() == k,
883 final(self)@ == old(self)@.remove(k),
884 {
885 use_type_invariant(&*self);
886
887 let tracked submap = self.split(iset![k]);
888 GhostIPointsTo { submap }
889 }
890
891 pub proof fn update(tracked &mut self, tracked auth: &mut GhostIMapAuth<K, V>, m: IMap<K, V>)
910 requires
911 m.dom() <= old(self)@.dom(),
912 old(self).id() == old(auth).id(),
913 ensures
914 final(self).id() == old(self).id(),
915 final(auth).id() == old(auth).id(),
916 final(self)@ == old(self)@.union_prefer_right(m),
917 final(auth)@ == old(auth)@.union_prefer_right(m),
918 {
919 broadcast use lemma_submap_of_trans;
920 broadcast use lemma_submap_of_op;
921
922 use_type_invariant(&*self);
923 use_type_invariant(&*auth);
924
925 let tracked mut mself = Self::dummy();
926 tracked_swap(self, &mut mself);
927 let tracked mut frac_r = mself.r;
928
929 let tracked mut mauth = GhostIMapAuth::<K, V>::dummy();
930 tracked_swap(auth, &mut mauth);
931 let tracked mut auth_r = mauth.r;
932
933 frac_r.validate_2(&auth_r);
934 let tracked mut full_r = frac_r.join(auth_r);
935
936 assert(full_r.value().frac.owning_map() == frac_r.value().frac.owning_map());
937
938 let auth_carrier = AuthCarrier::Auth(full_r.value().auth.map().union_prefer_right(m));
939 let frac_carrier = FracCarrier::Frac {
940 owning: full_r.value().frac.owning_map().union_prefer_right(m),
941 dup: IMap::empty(),
942 };
943 let new_full_carrier = IMapCarrier { auth: auth_carrier, frac: frac_carrier };
944
945 assert(new_full_carrier.valid());
946 let tracked r_upd = full_r.update(new_full_carrier);
947
948 let new_auth_carrier = IMapCarrier {
949 auth: r_upd.value().auth,
950 frac: FracCarrier::Frac { owning: IMap::empty(), dup: IMap::empty() },
951 };
952 let new_frac_carrier = IMapCarrier { auth: AuthCarrier::Frac, frac: r_upd.value().frac };
953 assert(r_upd.value().frac == IMapCarrier::op(new_auth_carrier, new_frac_carrier).frac);
954 assert(r_upd.value() == IMapCarrier::op(new_auth_carrier, new_frac_carrier));
955
956 let tracked (new_auth_r, new_frac_r) = r_upd.split(new_auth_carrier, new_frac_carrier);
957 auth.r = new_auth_r;
958 self.r = new_frac_r;
959 }
960
961 pub proof fn points_to(tracked self) -> (tracked r: GhostIPointsTo<K, V>)
963 requires
964 self.is_points_to(),
965 ensures
966 self@ == imap![r.key() => r.value()],
967 self.id() == r.id(),
968 {
969 let tracked r = GhostIPointsTo { submap: self };
970 r.lemma_map_view();
971 r
972 }
973
974 pub proof fn persist(tracked self) -> (tracked r: GhostPersistentISubmap<K, V>)
976 ensures
977 self@ == r@,
978 self.id() == r.id(),
979 {
980 broadcast use lemma_submap_of_trans;
981 broadcast use lemma_submap_of_op;
982
983 use_type_invariant(&self);
984
985 let tracked mut r = self.r;
986
987 let self_carrier = IMapCarrier {
988 auth: AuthCarrier::Frac,
989 frac: FracCarrier::Frac {
990 owning: self.r.value().frac.owning_map(),
991 dup: self.r.value().frac.dup_map(),
992 },
993 };
994
995 let res_carrier = IMapCarrier {
996 auth: AuthCarrier::Frac,
997 frac: FracCarrier::Frac {
998 owning: self.r.value().frac.dup_map(),
999 dup: self.r.value().frac.owning_map(),
1000 },
1001 };
1002
1003 let tracked r = r.update(res_carrier);
1004 GhostPersistentISubmap { r }
1005 }
1006}
1007
1008impl<K, V> GhostPersistentISubmap<K, V> {
1009 #[verifier::type_invariant]
1010 spec fn inv(self) -> bool {
1011 &&& self.r.value().auth is Frac
1012 &&& self.r.value().frac is Frac
1013 &&& self.r.value().frac.owning_map().is_empty()
1014 }
1015
1016 pub open spec fn is_points_to(self) -> bool {
1019 &&& self@.len() == 1
1020 &&& self.dom().finite()
1021 &&& !self@.is_empty()
1022 }
1023
1024 pub closed spec fn id(self) -> Loc {
1026 self.r.loc()
1027 }
1028
1029 pub closed spec fn view(self) -> IMap<K, V> {
1031 self.r.value().frac.dup_map()
1032 }
1033
1034 pub open spec fn dom(self) -> ISet<K> {
1036 self@.dom()
1037 }
1038
1039 pub open spec fn spec_index(self, key: K) -> V
1041 recommends
1042 self.dom().contains(key),
1043 {
1044 self@[key]
1045 }
1046
1047 pub proof fn dummy() -> (tracked result: GhostPersistentISubmap<K, V>) {
1049 let tracked owned = GhostISubmap::<K, V>::dummy();
1050 owned.persist()
1051 }
1052
1053 pub proof fn empty(tracked &self) -> (tracked result: GhostPersistentISubmap<K, V>)
1055 ensures
1056 result.id() == self.id(),
1057 result@ == IMap::<K, V>::empty(),
1058 {
1059 use_type_invariant(self);
1060 let tracked r = Resource::<IMapCarrier<_, _>>::create_unit(self.r.loc());
1061 GhostISubmap { r }.persist()
1062 }
1063
1064 pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentISubmap<K, V>)
1066 ensures
1067 result.id() == self.id(),
1068 result@ == self@,
1069 {
1070 use_type_invariant(&*self);
1071
1072 assert(IMapCarrier::op(self.r.value(), self.r.value()) == self.r.value());
1073 let tracked r = super::super::lib::duplicate(&self.r);
1074
1075 GhostPersistentISubmap { r }
1076 }
1077
1078 pub proof fn agree(
1098 tracked self: &GhostPersistentISubmap<K, V>,
1099 tracked auth: &GhostIMapAuth<K, V>,
1100 )
1101 requires
1102 self.id() == auth.id(),
1103 ensures
1104 self@ <= auth@,
1105 {
1106 broadcast use lemma_submap_of_trans;
1107
1108 use_type_invariant(self);
1109 use_type_invariant(auth);
1110
1111 let tracked joined = self.r.join_shared(&auth.r);
1112 joined.validate();
1113 assert(self.r.value().frac.dup_map() <= joined.value().frac.dup_map());
1114 }
1115
1116 pub proof fn combine(tracked &mut self, tracked other: GhostPersistentISubmap<K, V>)
1120 requires
1121 old(self).id() == other.id(),
1122 ensures
1123 final(self).id() == old(self).id(),
1124 final(self)@ == old(self)@.union_prefer_right(other@),
1125 old(self)@.agrees(other@),
1126 {
1127 use_type_invariant(&*self);
1128 use_type_invariant(&other);
1129
1130 self.r.validate_2(&other.r);
1131 incorporate(&mut self.r, other.r);
1132 }
1133
1134 pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPersistentIPointsTo<K, V>)
1137 requires
1138 old(self).id() == other.id(),
1139 ensures
1140 final(self).id() == old(self).id(),
1141 final(self)@ == old(self)@.insert(other.key(), other.value()),
1142 old(self)@.contains_key(other.key()) ==> old(self)@[other.key()] == other.value(),
1143 {
1144 use_type_invariant(&*self);
1145 use_type_invariant(&other);
1146
1147 other.lemma_map_view();
1148 self.combine(other.submap);
1149 }
1150
1151 pub proof fn disjoint(tracked &mut self, tracked other: &GhostISubmap<K, V>)
1153 requires
1154 old(self).id() == other.id(),
1155 ensures
1156 final(self).id() == old(self).id(),
1157 final(self)@ == old(self)@,
1158 final(self)@.dom().disjoint(other@.dom()),
1159 {
1160 use_type_invariant(&*self);
1161 use_type_invariant(other);
1162 self.r.validate_2(&other.r);
1163 }
1164
1165 pub proof fn intersection_agrees(
1167 tracked &mut self,
1168 tracked other: &GhostPersistentISubmap<K, V>,
1169 )
1170 requires
1171 old(self).id() == other.id(),
1172 ensures
1173 final(self).id() == old(self).id(),
1174 final(self)@ == old(self)@,
1175 final(self)@.agrees(other@),
1176 {
1177 use_type_invariant(&*self);
1178 use_type_invariant(other);
1179 self.r.validate_2(&other.r);
1180 }
1181
1182 pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostIPointsTo<K, V>)
1185 requires
1186 old(self).id() == other.id(),
1187 ensures
1188 final(self).id() == old(self).id(),
1189 final(self)@ == old(self)@,
1190 !final(self)@.contains_key(other.key()),
1191 {
1192 use_type_invariant(&*self);
1193 use_type_invariant(other);
1194 self.disjoint(&other.submap);
1195 }
1196
1197 pub proof fn intersection_agrees_points_to(
1201 tracked &mut self,
1202 tracked other: &GhostPersistentIPointsTo<K, V>,
1203 )
1204 requires
1205 old(self).id() == other.id(),
1206 ensures
1207 final(self).id() == old(self).id(),
1208 final(self)@ == old(self)@,
1209 final(self)@.contains_key(other.key()) ==> final(self)@[other.key()] == other.value(),
1210 {
1211 use_type_invariant(&*self);
1212 use_type_invariant(other);
1213 self.intersection_agrees(&other.submap);
1214 }
1215
1216 pub proof fn split(tracked &mut self, s: ISet<K>) -> (tracked result: GhostPersistentISubmap<
1218 K,
1219 V,
1220 >)
1221 requires
1222 s <= old(self)@.dom(),
1223 ensures
1224 final(self).id() == old(self).id(),
1225 result.id() == final(self).id(),
1226 old(self)@ == final(self)@.union_prefer_right(result@),
1227 result@.dom() =~= s,
1228 final(self)@.dom() =~= old(self)@.dom() - s,
1229 {
1230 use_type_invariant(&*self);
1231
1232 let tracked mut r = Resource::alloc(IMapCarrier::<K, V>::unit());
1233 tracked_swap(&mut self.r, &mut r);
1234
1235 let self_carrier = IMapCarrier {
1236 auth: AuthCarrier::Frac,
1237 frac: FracCarrier::Frac {
1238 owning: r.value().frac.owning_map(),
1239 dup: r.value().frac.dup_map().remove_keys(s),
1240 },
1241 };
1242
1243 let res_carrier = IMapCarrier {
1244 auth: AuthCarrier::Frac,
1245 frac: FracCarrier::Frac {
1246 owning: r.value().frac.owning_map(),
1247 dup: r.value().frac.dup_map().restrict(s),
1248 },
1249 };
1250
1251 assert(r.value().frac == IMapCarrier::op(self_carrier, res_carrier).frac);
1252 let tracked (self_r, res_r) = r.split(self_carrier, res_carrier);
1253 self.r = self_r;
1254 GhostPersistentISubmap { r: res_r }
1255 }
1256
1257 pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result:
1259 GhostPersistentIPointsTo<K, V>)
1260 requires
1261 old(self)@.contains_key(k),
1262 ensures
1263 final(self).id() == old(self).id(),
1264 result.id() == final(self).id(),
1265 old(self)@ == final(self)@.insert(result.key(), result.value()),
1266 result.key() == k,
1267 final(self)@ == old(self)@.remove(k),
1268 {
1269 use_type_invariant(&*self);
1270
1271 let tracked submap = self.split(iset![k]);
1272 GhostPersistentIPointsTo { submap }
1273 }
1274
1275 pub proof fn points_to(tracked self) -> (tracked r: GhostPersistentIPointsTo<K, V>)
1277 requires
1278 self.is_points_to(),
1279 ensures
1280 self@ == imap![r.key() => r.value()],
1281 self.id() == r.id(),
1282 {
1283 let tracked r = GhostPersistentIPointsTo { submap: self };
1284 r.lemma_map_view();
1285 r
1286 }
1287}
1288
1289impl<K, V> GhostIPointsTo<K, V> {
1290 #[verifier::type_invariant]
1291 spec fn inv(self) -> bool {
1292 self.submap.is_points_to()
1293 }
1294
1295 pub closed spec fn id(self) -> Loc {
1297 self.submap.id()
1298 }
1299
1300 pub open spec fn view(self) -> (K, V) {
1302 (self.key(), self.value())
1303 }
1304
1305 pub closed spec fn key(self) -> K {
1307 self.submap.dom().choose()
1308 }
1309
1310 pub closed spec fn value(self) -> V {
1312 self.submap[self.key()]
1313 }
1314
1315 pub proof fn agree(tracked self: &GhostIPointsTo<K, V>, tracked auth: &GhostIMapAuth<K, V>)
1333 requires
1334 self.id() == auth.id(),
1335 ensures
1336 auth@.contains_pair(self.key(), self.value()),
1337 {
1338 use_type_invariant(self);
1339 use_type_invariant(auth);
1340
1341 self.lemma_map_view();
1342 self.submap.agree(auth);
1343 assert(self.submap@ <= auth@);
1344 assert(self.submap@.dom().contains(self.key()));
1345 assert(auth@.dom().contains(self.key()));
1346 assert(self.submap@[self.key()] == self.value());
1347 assert(auth@[self.key()] == self.value());
1348 }
1349
1350 pub proof fn combine(tracked self, tracked other: GhostIPointsTo<K, V>) -> (tracked r:
1353 GhostISubmap<K, V>)
1354 requires
1355 self.id() == other.id(),
1356 ensures
1357 r.id() == self.id(),
1358 r@ == imap![self.key() => self.value(), other.key() => other.value()],
1359 self.key() != other.key(),
1360 {
1361 use_type_invariant(&self);
1362 use_type_invariant(&other);
1363
1364 let tracked mut submap = self.submap();
1365 submap.combine_points_to(other);
1366
1367 submap
1368 }
1369
1370 pub proof fn disjoint(tracked &mut self, tracked other: &GhostIPointsTo<K, V>)
1372 requires
1373 old(self).id() == other.id(),
1374 ensures
1375 final(self).id() == old(self).id(),
1376 final(self)@ == old(self)@,
1377 final(self).key() != other.key(),
1378 {
1379 use_type_invariant(&*self);
1380 use_type_invariant(other);
1381 self.submap.disjoint(&other.submap);
1382 }
1383
1384 pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostISubmap<K, V>)
1386 requires
1387 old(self).id() == other.id(),
1388 ensures
1389 final(self).id() == old(self).id(),
1390 final(self)@ == old(self)@,
1391 !other.dom().contains(final(self).key()),
1392 {
1393 use_type_invariant(&*self);
1394 use_type_invariant(other);
1395 self.submap.disjoint(other);
1396 }
1397
1398 pub proof fn disjoint_persistent_submap(
1400 tracked &mut self,
1401 tracked other: &GhostPersistentISubmap<K, V>,
1402 )
1403 requires
1404 old(self).id() == other.id(),
1405 ensures
1406 final(self).id() == old(self).id(),
1407 final(self)@ == old(self)@,
1408 !other.dom().contains(final(self).key()),
1409 {
1410 use_type_invariant(&*self);
1411 use_type_invariant(other);
1412 self.submap.disjoint_persistent(other);
1413 }
1414
1415 pub proof fn disjoint_persistent(
1417 tracked &mut self,
1418 tracked other: &GhostPersistentIPointsTo<K, V>,
1419 )
1420 requires
1421 old(self).id() == other.id(),
1422 ensures
1423 final(self).id() == old(self).id(),
1424 final(self)@ == old(self)@,
1425 final(self).key() != other.key(),
1426 {
1427 use_type_invariant(&*self);
1428 use_type_invariant(other);
1429 self.submap.disjoint_persistent_points_to(other);
1430 }
1431
1432 pub proof fn update(tracked &mut self, tracked auth: &mut GhostIMapAuth<K, V>, v: V)
1434 requires
1435 old(self).id() == old(auth).id(),
1436 ensures
1437 final(self).id() == old(self).id(),
1438 final(auth).id() == old(auth).id(),
1439 final(self).key() == old(self).key(),
1440 final(self)@ == (final(self).key(), v),
1441 final(auth)@ == old(auth)@.union_prefer_right(imap![final(self).key() => v]),
1442 {
1443 broadcast use lemma_submap_of_trans;
1444 broadcast use lemma_submap_of_op;
1445
1446 use_type_invariant(&*self);
1447 use_type_invariant(&*auth);
1448
1449 let ghost old_dom = self.submap.dom();
1450 self.lemma_map_view();
1451 let m = imap![self.key() => v];
1452 assert(self.submap@.union_prefer_right(m) == m);
1453 self.submap.update(auth, m);
1454 }
1455
1456 pub proof fn submap(tracked self) -> (tracked r: GhostISubmap<K, V>)
1458 ensures
1459 r.id() == self.id(),
1460 r@ == imap![self.key() => self.value()],
1461 {
1462 self.lemma_map_view();
1463 self.submap
1464 }
1465
1466 proof fn lemma_map_view(tracked &self)
1467 ensures
1468 self.submap@ == imap![self.key() => self.value()],
1469 {
1470 use_type_invariant(self);
1471 let key = self.key();
1472 let target_dom = iset![key];
1473
1474 assert(self.submap@.dom().len() == 1);
1475 assert(target_dom.len() == 1);
1476
1477 assert(self.submap@.dom().finite());
1478 assert(target_dom.finite());
1479
1480 assert(self.submap@.dom().contains(key));
1481 assert(target_dom.contains(key));
1482
1483 assert(self.submap@.dom().remove(key).len() == 0);
1484 assert(target_dom.remove(key).len() == 0);
1485
1486 assert(self.submap@.dom() =~= target_dom);
1487 assert(self.submap@ == imap![self.key() => self.value()]);
1488 }
1489
1490 pub proof fn lemma_view(self)
1492 ensures
1493 self@ == (self.key(), self.value()),
1494 {
1495 }
1496
1497 pub proof fn persist(tracked self) -> (tracked r: GhostPersistentIPointsTo<K, V>)
1499 ensures
1500 self@ == r@,
1501 self.id() == r.id(),
1502 {
1503 use_type_invariant(&self);
1504 self.submap.persist().points_to()
1505 }
1506}
1507
1508impl<K, V> GhostPersistentIPointsTo<K, V> {
1509 #[verifier::type_invariant]
1510 spec fn inv(self) -> bool {
1511 self.submap.is_points_to()
1512 }
1513
1514 pub closed spec fn id(self) -> Loc {
1516 self.submap.id()
1517 }
1518
1519 pub open spec fn view(self) -> (K, V) {
1521 (self.key(), self.value())
1522 }
1523
1524 pub closed spec fn key(self) -> K {
1526 self.submap.dom().choose()
1527 }
1528
1529 pub closed spec fn value(self) -> V {
1531 self.submap[self.key()]
1532 }
1533
1534 pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentIPointsTo<K, V>)
1536 ensures
1537 result.id() == self.id(),
1538 result@ == self@,
1539 {
1540 use_type_invariant(&*self);
1541 let tracked submap = self.submap.duplicate();
1542 GhostPersistentIPointsTo { submap }
1543 }
1544
1545 pub proof fn agree(
1563 tracked self: &GhostPersistentIPointsTo<K, V>,
1564 tracked auth: &GhostIMapAuth<K, V>,
1565 )
1566 requires
1567 self.id() == auth.id(),
1568 ensures
1569 auth@.contains_pair(self.key(), self.value()),
1570 {
1571 use_type_invariant(self);
1572 use_type_invariant(auth);
1573
1574 self.lemma_map_view();
1575 self.submap.agree(auth);
1576 assert(self.submap@ <= auth@);
1577 assert(self.submap@.contains_key(self.key()));
1578 }
1579
1580 pub proof fn combine(
1582 tracked self,
1583 tracked other: GhostPersistentIPointsTo<K, V>,
1584 ) -> (tracked submap: GhostPersistentISubmap<K, V>)
1585 requires
1586 self.id() == other.id(),
1587 ensures
1588 submap.id() == self.id(),
1589 submap@ == imap![self.key() => self.value(), other.key() => other.value()],
1590 self.key() != other.key() ==> submap@.len() == 2,
1591 self.key() == other.key() ==> submap@.len() == 1,
1592 {
1593 use_type_invariant(&self);
1594 use_type_invariant(&other);
1595
1596 let tracked mut submap = self.submap();
1597 submap.combine_points_to(other);
1598
1599 submap
1600 }
1601
1602 pub proof fn disjoint(tracked &mut self, tracked other: &GhostIPointsTo<K, V>)
1605 requires
1606 old(self).id() == other.id(),
1607 ensures
1608 final(self).id() == old(self).id(),
1609 final(self)@ == old(self)@,
1610 final(self).key() != other.key(),
1611 {
1612 use_type_invariant(&*self);
1613 use_type_invariant(other);
1614 self.disjoint_submap(&other.submap);
1615 }
1616
1617 pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostISubmap<K, V>)
1620 requires
1621 old(self).id() == other.id(),
1622 ensures
1623 final(self).id() == old(self).id(),
1624 final(self)@ == old(self)@,
1625 !other@.contains_key(final(self).key()),
1626 {
1627 use_type_invariant(&*self);
1628 use_type_invariant(other);
1629 self.submap.disjoint(&other);
1630 }
1631
1632 pub proof fn intersection_agrees(
1635 tracked &mut self,
1636 tracked other: &GhostPersistentIPointsTo<K, V>,
1637 )
1638 requires
1639 old(self).id() == other.id(),
1640 ensures
1641 final(self).id() == old(self).id(),
1642 final(self)@ == old(self)@,
1643 final(self).key() == other.key() ==> final(self).value() == other.value(),
1644 {
1645 use_type_invariant(&*self);
1646 use_type_invariant(other);
1647 self.submap.intersection_agrees_points_to(&other);
1648 }
1649
1650 pub proof fn intersection_agrees_submap(
1652 tracked &mut self,
1653 tracked other: &GhostPersistentISubmap<K, V>,
1654 )
1655 requires
1656 old(self).id() == other.id(),
1657 ensures
1658 final(self).id() == old(self).id(),
1659 final(self)@ == old(self)@,
1660 other@.contains_key(final(self).key()) ==> other@[final(self).key()]
1661 == final(self).value(),
1662 {
1663 use_type_invariant(&*self);
1664 use_type_invariant(other);
1665 self.submap.intersection_agrees(other);
1666 }
1667
1668 pub proof fn submap(tracked self) -> (tracked r: GhostPersistentISubmap<K, V>)
1670 ensures
1671 r.id() == self.id(),
1672 r@ == imap![self.key() => self.value()],
1673 {
1674 self.lemma_map_view();
1675 self.submap
1676 }
1677
1678 proof fn lemma_map_view(tracked &self)
1679 ensures
1680 self.submap@ == imap![self.key() => self.value()],
1681 {
1682 use_type_invariant(self);
1683 let key = self.key();
1684 let target_dom = iset![key];
1685
1686 assert(self.submap@.dom().len() == 1);
1687 assert(target_dom.len() == 1);
1688
1689 assert(self.submap@.dom().finite());
1690 assert(target_dom.finite());
1691
1692 assert(self.submap@.dom().contains(key));
1693 assert(target_dom.contains(key));
1694
1695 assert(self.submap@.dom().remove(key).len() == 0);
1696 assert(target_dom.remove(key).len() == 0);
1697
1698 assert(self.submap@.dom() =~= target_dom);
1699 assert(self.submap@ == imap![self.key() => self.value()]);
1700 }
1701
1702 pub proof fn lemma_view(self)
1704 ensures
1705 self@ == (self.key(), self.value()),
1706 {
1707 }
1708}
1709
1710}