vstd/tokens/
map.rs

1//! Maps that support ownership of keys
2//!
3//! - [`GhostMapAuth<K, V>`] represents authoritative ownership of the entire map;
4//! - [`GhostSubmap<K, V>`] represents client ownership of a submap;
5//! - [`GhostPersistentSubmap<K, V>`] represents duplicable client knowledge of a submap which will never change;
6//! - [`GhostPointsTo<K, V>`] represents client ownership of a single key-value pair.
7//! - [`GhostPersistentPointsTo<K, V>`] represents duplicable client knowledge of a single key-value pair which will never change.
8//!
9//! Updating the authoritative `GhostMapAuth<K, V>` requires a `GhostSubmap<K, V>` containing the keys being updated.
10//!
11//! `GhostSubmap<K, V>`s can be combined or split.
12//! Whenever a `GhostSubmap<K, V>` can be used, we can instead use a `GhostPointsTo<K, V>` (but not vice-versa).
13//!
14//! `GhostPersistentSubmap<K, V>`s can be combined or split.
15//! Whenever a `GhostPersistentSubmap<K, V>` can be used, we can instead use a `GhostPersistentPointsTo<K, V>` (but not vice-versa).
16//!
17//! ### Example
18//!
19//! ```
20//! fn example_use() {
21//!     let tracked (mut auth, mut sub) = GhostMapAuth::new(map![1u8 => 1u64, 2u8 => 2u64, 3u8 => 3u64]);
22//!
23//!     // Allocate some more keys in the auth map, receiving a new submap.
24//!     let tracked sub2 = auth.insert_map(map![4u8 => 4u64, 5u8 => 5u64]);
25//!     proof { sub.combine(sub2); }
26//!
27//!     // Allocate a single key in the auth map, receiving a points to
28//!     let tracked pt1 = auth.insert(6u8, 6u64);
29//!     proof { sub.combine_points_to(pt1); }
30//!
31//!     // Delete some keys in the auth map, by returning corresponding submap.
32//!     let tracked sub3 = sub.split(set![3u8, 4u8]);
33//!     proof { auth.delete(sub3); }
34//!
35//!     // Split the submap into a points to and a submap
36//!     let tracked pt2 = sub.split_points_to(1u8);
37//!     let tracked sub4 = sub.split(set![5u8, 6u8]);
38//!
39//!     // In general, we might need to call agree() to establish the fact that
40//!     // a points-to/submap has the same values as the auth map.  Here, Verus
41//!     // doesn't need agree because it can track where both the auth, points-to
42//!     // and submap came from.
43//!     proof { sub.agree(&auth); }
44//!     proof { pt2.agree(&auth); }
45//!     proof { sub4.agree(&auth); }
46//!
47//!     assert(pt2.key() == 1u8);
48//!     assert(pt2.value() == auth[1u8]);
49//!     assert(sub4[5u8] == auth[5u8]);
50//!     assert(sub4[6u8] == auth[6u8]);
51//!     assert(sub[2u8] == auth[2u8]);
52//!
53//!     // Update keys using ownership of submaps.
54//!     proof { sub.update(&mut auth, map![2u8 => 22u64]); }
55//!     proof { pt2.update(&mut auth, 11u64); }
56//!     proof { sub4.update(&mut auth, map![5u8 => 55u64, 6u8 => 66u8]); }
57//!     assert(auth[1u8] == 11u64);
58//!     assert(auth[2u8] == 22u64);
59//!     assert(auth[5u8] == 55u64);
60//!     assert(auth[6u8] == 66u64);
61//!
62//!     // Persist and duplicate the submap
63//!     let mut psub1 = sub.persist();
64//!     assert(psub1[2u8] == 22u64);
65//!     let psub2 = psub1.duplicate();
66//!     assert(psub2[2u8] == 22u64);
67//!
68//!     // Not shown in this simple example is the main use case of this resource:
69//!     // maintaining an invariant between GhostMapAuth<K, V> and some exec-mode
70//!     // shared state with a map view (e.g., HashMap<K, V>), which states that
71//!     // the Map<K, V> view of GhostMapAuth<K, V> is the same as the view of the
72//!     // HashMap<K, V>, and then handing out a GhostSubmap<K, V> to different
73//!     // clients that might need to operate on different keys in this map.
74//! }
75//! ```
76use super::super::map::*;
77use super::super::map_lib::*;
78use super::super::modes::*;
79use super::super::pcm::*;
80use super::super::prelude::*;
81use super::super::set_lib::*;
82
83verus! {
84
85broadcast use super::super::group_vstd_default;
86
87#[verifier::reject_recursive_types(K)]
88#[verifier::ext_equal]
89enum AuthCarrier<K, V> {
90    Auth(Map<K, V>),
91    Frac,
92    Invalid,
93}
94
95#[verifier::reject_recursive_types(K)]
96#[verifier::ext_equal]
97enum FracCarrier<K, V> {
98    Frac { owning: Map<K, V>, dup: Map<K, V> },
99    Invalid,
100}
101
102impl<K, V> AuthCarrier<K, V> {
103    spec fn valid(self) -> bool {
104        !(self is Invalid)
105    }
106
107    spec fn map(self) -> Map<K, V>
108        recommends
109            self.valid(),
110    {
111        match self {
112            AuthCarrier::Auth(m) => m,
113            AuthCarrier::Frac => Map::empty(),
114            AuthCarrier::Invalid => Map::empty(),
115        }
116    }
117}
118
119impl<K, V> FracCarrier<K, V> {
120    spec fn valid(self) -> bool {
121        match self {
122            FracCarrier::Invalid => false,
123            FracCarrier::Frac { owning, dup } => owning.dom().disjoint(dup.dom()),
124        }
125    }
126
127    spec fn owning_map(self) -> Map<K, V> {
128        match self {
129            FracCarrier::Frac { owning, .. } => owning,
130            FracCarrier::Invalid => Map::empty(),
131        }
132    }
133
134    spec fn dup_map(self) -> Map<K, V> {
135        match self {
136            FracCarrier::Frac { dup, .. } => dup,
137            FracCarrier::Invalid => Map::empty(),
138        }
139    }
140}
141
142#[verifier::reject_recursive_types(K)]
143#[verifier::ext_equal]
144// This struct represents the underlying resource algebra for GhostMaps
145struct MapCarrier<K, V> {
146    auth: AuthCarrier<K, V>,
147    frac: FracCarrier<K, V>,
148}
149
150impl<K, V> PCM for MapCarrier<K, V> {
151    closed spec fn valid(self) -> bool {
152        match (self.auth, self.frac) {
153            (AuthCarrier::Invalid, _) => false,
154            (_, FracCarrier::Invalid) => false,
155            (AuthCarrier::Auth(auth), FracCarrier::Frac { owning, dup }) => {
156                &&& owning <= auth
157                &&& dup <= auth
158                &&& owning.dom().disjoint(dup.dom())
159            },
160            (AuthCarrier::Frac, FracCarrier::Frac { owning, dup }) => owning.dom().disjoint(
161                dup.dom(),
162            ),
163        }
164    }
165
166    closed spec fn op(self, other: Self) -> Self {
167        let auth = match (self.auth, other.auth) {
168            // Invalid carriers absorb
169            (AuthCarrier::Invalid, _) => AuthCarrier::Invalid,
170            (_, AuthCarrier::Invalid) => AuthCarrier::Invalid,
171            // There can't be two auths
172            (AuthCarrier::Auth(_), AuthCarrier::Auth(_)) => AuthCarrier::Invalid,
173            // Fracs remain the same
174            (AuthCarrier::Frac, AuthCarrier::Frac) => AuthCarrier::Frac,
175            // Whoever is the auth has precedence
176            (AuthCarrier::Auth(_), _) => self.auth,
177            (_, AuthCarrier::Auth(_)) => other.auth,
178        };
179
180        let frac = match (self.frac, other.frac) {
181            // Invalid fracs remain invalid
182            (FracCarrier::Invalid, _) => FracCarrier::Invalid,
183            (_, FracCarrier::Invalid) => FracCarrier::Invalid,
184            // We can mix two owning fracs iff they are disjoint -- we get the union
185            // There is a tricky element here:
186            //  - one of the fracs may be invalid due to their maps overlapping
187            //  - there is no real way to express this in the typesystem
188            //  - we need to allow that through (because it does not equal Invalid)
189            (
190                FracCarrier::Frac { owning: self_owning, dup: self_dup },
191                FracCarrier::Frac { owning: other_owning, dup: other_dup },
192            ) => {
193                let non_overlapping = {
194                    &&& self_owning.dom().disjoint(other_dup.dom())
195                    &&& other_owning.dom().disjoint(self_dup.dom())
196                    &&& self_owning.dom().disjoint(other_owning.dom())
197                };
198                let aggreement = self_dup.agrees(other_dup);
199                if non_overlapping && aggreement {
200                    FracCarrier::Frac {
201                        owning: self_owning.union_prefer_right(other_owning),
202                        dup: self_dup.union_prefer_right(other_dup),
203                    }
204                } else {
205                    FracCarrier::Invalid
206                }
207            },
208        };
209
210        MapCarrier { auth, frac }
211    }
212
213    closed spec fn unit() -> Self {
214        MapCarrier {
215            auth: AuthCarrier::Frac,
216            frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
217        }
218    }
219
220    proof fn closed_under_incl(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        // derive contradiction that the items are disjoint
226        if !a.frac.owning_map().dom().disjoint(a.frac.dup_map().dom()) {
227            // The intersection is not empty
228            lemma_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));  // CONTRADICTION
235        };
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    proof fn op_unit(a: Self) {
253        let x = Self::op(a, Self::unit());
254        assert(a == x);
255    }
256
257    proof fn unit_valid() {
258    }
259}
260
261proof fn lemma_submap_of_op_frac<K, V>(a: MapCarrier<K, V>, b: MapCarrier<K, V>)
262    requires
263        MapCarrier::op(a, b).valid(),
264    ensures
265        a.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
266        a.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
267        b.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
268        b.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
269{
270    let ab = MapCarrier::op(a, b);
271    assert(ab.frac.owning_map() == a.frac.owning_map().union_prefer_right(b.frac.owning_map()));
272    assert(ab.frac.dup_map() == a.frac.dup_map().union_prefer_right(b.frac.dup_map()));
273    assert(a.frac.owning_map().dom().disjoint(b.frac.owning_map().dom()));
274}
275
276broadcast proof fn lemma_submap_of_op<K, V>(a: MapCarrier<K, V>, b: MapCarrier<K, V>)
277    requires
278        #[trigger] MapCarrier::op(a, b).valid(),
279    ensures
280        a.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
281        a.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
282        a.auth.map() <= MapCarrier::op(a, b).auth.map(),
283        b.frac.owning_map() <= MapCarrier::op(a, b).frac.owning_map(),
284        b.frac.dup_map() <= MapCarrier::op(a, b).frac.dup_map(),
285        b.auth.map() <= MapCarrier::op(a, b).auth.map(),
286        a.valid(),
287        b.valid(),
288{
289    lemma_submap_of_op_frac(a, b);
290    MapCarrier::closed_under_incl(a, b);
291    MapCarrier::commutative(a, b);
292    MapCarrier::closed_under_incl(b, a);
293    let ab = MapCarrier::op(a, b);
294    assert(ab.auth.map() == a.auth.map().union_prefer_right(b.auth.map()));
295}
296
297/// A resource that has the authoritative ownership on the entire map
298#[verifier::reject_recursive_types(K)]
299pub struct GhostMapAuth<K, V> {
300    r: Resource<MapCarrier<K, V>>,
301}
302
303/// A resource that asserts client ownership of a submap.
304///
305/// The existence of a [`GhostSubmap`] implies that:
306///  - Those keys will remain in the map (unless the onwer of the [`GhostSubmap`] deletes it using [`GhostMapAuth::delete`]);
307///  - Those keys will remain pointing to the same values (unless the onwer of the [`GhostSubmap`] updates them using [`GhostSubmap::update`])
308///  - All other [`GhostSubmap`]/[`GhostPointsTo`]/[`GhostPersistentSubmap`]/[`GhostPersistentPointsTo`] are disjoint subsets of the domain
309#[verifier::reject_recursive_types(K)]
310pub struct GhostSubmap<K, V> {
311    r: Resource<MapCarrier<K, V>>,
312}
313
314/// A resource representing duplicable client knowledge of a persistent submap.
315///
316/// The existence of a [`GhostPersistentSubmap`] implies that:
317///  - Those keys will remain in the map, pointing to the same values, forever;
318///  - All other [`GhostSubmap`]/[`GhostPointsTo`]/[`GhostPersistentSubmap`]/[`GhostPersistentPointsTo`] are disjoint subsets of the domain
319#[verifier::reject_recursive_types(K)]
320pub struct GhostPersistentSubmap<K, V> {
321    r: Resource<MapCarrier<K, V>>,
322}
323
324/// A resource that asserts client ownership over a single key in the map.
325///
326/// The existence of a [`GhostPointsTo`] implies that:
327///  - Those key will remain in the map (unless the onwer of the [`GhostPointsTo`] deletes it using [`GhostMapAuth::delete_points_to`]);
328///  - Those key will remain pointing to the same value (unless the onwer of the [`GhostPointsTo`] updates them using [`GhostPointsTo::update`])
329///  - All other [`GhostSubmap`]/[`GhostPointsTo`]/[`GhostPersistentSubmap`]/[`GhostPersistentPointsTo`] are disjoint subsets of the domain
330#[verifier::reject_recursive_types(K)]
331pub struct GhostPointsTo<K, V> {
332    submap: GhostSubmap<K, V>,
333}
334
335/// A resource representing duplicable client knowledge of a single key in the map.
336///
337/// The existence of a [`GhostPersistentPointsTo`] implies that:
338///  - The key-value pair will remain in the map, forever;
339///  - All other [`GhostSubmap`]/[`GhostPointsTo`]/[`GhostPersistentSubmap`]/[`GhostPersistentPointsTo`] are disjoint subsets of the domain
340#[verifier::reject_recursive_types(K)]
341pub struct GhostPersistentPointsTo<K, V> {
342    submap: GhostPersistentSubmap<K, V>,
343}
344
345impl<K, V> GhostMapAuth<K, V> {
346    #[verifier::type_invariant]
347    spec fn inv(self) -> bool {
348        &&& self.r.value().auth is Auth
349        &&& self.r.value().frac == FracCarrier::Frac {
350            owning: Map::<K, V>::empty(),
351            dup: Map::<K, V>::empty(),
352        }
353    }
354
355    /// Resource location
356    pub closed spec fn id(self) -> Loc {
357        self.r.loc()
358    }
359
360    /// Logically underlying [`Map`]
361    pub closed spec fn view(self) -> Map<K, V> {
362        self.r.value().auth.map()
363    }
364
365    /// Domain of the [`GhostMapAuth`]
366    pub open spec fn dom(self) -> Set<K> {
367        self@.dom()
368    }
369
370    /// Indexing operation `auth[key]`
371    pub open spec fn spec_index(self, key: K) -> V
372        recommends
373            self.dom().contains(key),
374    {
375        self@[key]
376    }
377
378    /// Instantiate a dummy [`GhostMapAuth`]
379    pub proof fn dummy() -> (tracked result: GhostMapAuth<K, V>) {
380        let tracked (auth, submap) = GhostMapAuth::<K, V>::new(Map::empty());
381        auth
382    }
383
384    /// Extract the [`GhostMapAuth`] from a mutable reference
385    pub proof fn take(tracked &mut self) -> (tracked result: GhostMapAuth<K, V>)
386        ensures
387            result == *old(self),
388    {
389        use_type_invariant(&*self);
390        let tracked mut r = Self::dummy();
391        tracked_swap(self, &mut r);
392        r
393    }
394
395    /// Create an empty [`GhostSubmap`]
396    pub proof fn empty(tracked &self) -> (tracked result: GhostSubmap<K, V>)
397        ensures
398            result.id() == self.id(),
399            result@ == Map::<K, V>::empty(),
400    {
401        use_type_invariant(self);
402        GhostSubmap::<K, V>::empty(self.id())
403    }
404
405    /// Insert a [`Map`] of values, receiving the [`GhostSubmap`] that asserts ownership over the key
406    /// domain inserted.
407    ///
408    /// ```
409    /// proof fn insert_map_example(tracked mut m: GhostMapAuth<int, int>) -> (tracked r: GhostSubmap<int, int>)
410    ///     requires
411    ///         !m.dom().contains(1int),
412    ///         !m.dom().contains(2int),
413    /// {
414    ///     let tracked submap = m.insert_map(map![1int => 1int, 2int => 4int]);
415    ///     // do something with the submap
416    ///     submap
417    /// }
418    /// ```
419    pub proof fn insert_map(tracked &mut self, m: Map<K, V>) -> (tracked result: GhostSubmap<K, V>)
420        requires
421            old(self)@.dom().disjoint(m.dom()),
422        ensures
423            self.id() == old(self).id(),
424            self@ == old(self)@.union_prefer_right(m),
425            result.id() == self.id(),
426            result@ == m,
427    {
428        broadcast use lemma_submap_of_trans;
429        broadcast use lemma_submap_of_op;
430
431        let tracked mut mself = Self::dummy();
432        tracked_swap(self, &mut mself);
433
434        use_type_invariant(&mself);
435        assert(mself.inv());
436        let tracked mut self_r = mself.r;
437
438        let full_carrier = MapCarrier {
439            auth: AuthCarrier::Auth(self_r.value().auth.map().union_prefer_right(m)),
440            frac: FracCarrier::Frac { owning: m, dup: Map::empty() },
441        };
442
443        assert(full_carrier.valid());
444        let tracked updated_r = self_r.update(full_carrier);
445
446        let auth_carrier = MapCarrier {
447            auth: updated_r.value().auth,
448            frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
449        };
450        let frac_carrier = MapCarrier { auth: AuthCarrier::Frac, frac: updated_r.value().frac };
451
452        assert(updated_r.value() == MapCarrier::op(auth_carrier, frac_carrier));
453        let tracked (auth_r, frac_r) = updated_r.split(auth_carrier, frac_carrier);
454        self.r = auth_r;
455        GhostSubmap { r: frac_r }
456    }
457
458    /// Insert a key-value pair, receiving the [`GhostPointsTo`] that asserts ownerships over the key.
459    ///
460    /// ```
461    /// proof fn insert_example(tracked mut m: GhostMapAuth<int, int>) -> (tracked r: GhostPointsTo<int, int>)
462    ///     requires
463    ///         !m.dom().contains(1int),
464    /// {
465    ///     let tracked points_to = m.insert(1, 1);
466    ///     // do something with the points_to
467    ///     points_to
468    /// }
469    /// ```
470    pub proof fn insert(tracked &mut self, k: K, v: V) -> (tracked result: GhostPointsTo<K, V>)
471        requires
472            !old(self)@.contains_key(k),
473        ensures
474            self.id() == old(self).id(),
475            self@ == old(self)@.insert(k, v),
476            result.id() == self.id(),
477            result@ == (k, v),
478    {
479        let tracked submap = self.insert_map(map![k => v]);
480        GhostPointsTo { submap }
481    }
482
483    /// Delete a set of keys
484    /// ```
485    /// proof fn delete(tracked mut auth: GhostMapAuth<int, int>)
486    ///     requires
487    ///         auth.dom().contains(1int),
488    ///         auth.dom().contains(2int),
489    ///     ensures
490    ///         old(auth)@ == auth@
491    /// {
492    ///     let tracked submap = auth.insert_map(map![1int => 1int, 2int => 4int]);
493    ///     // do something with the submap
494    ///     auth.delete(submap)
495    /// }
496    /// ```
497    pub proof fn delete(tracked &mut self, tracked submap: GhostSubmap<K, V>)
498        requires
499            submap.id() == old(self).id(),
500        ensures
501            self.id() == old(self).id(),
502            self@ == old(self)@.remove_keys(submap@.dom()),
503    {
504        broadcast use lemma_submap_of_trans;
505        broadcast use lemma_submap_of_op;
506
507        use_type_invariant(&*self);
508        use_type_invariant(&submap);
509
510        let tracked mut mself = Self::dummy();
511        tracked_swap(self, &mut mself);
512        let tracked mut self_r = mself.r;
513
514        // join the resource with the original carrier
515        self_r = self_r.join(submap.r);
516
517        // remove keys from the map
518        let auth_map = self_r.value().auth.map();
519        let new_auth_map = auth_map.remove_keys(submap@.dom());
520
521        let new_r = MapCarrier {
522            auth: AuthCarrier::Auth(new_auth_map),
523            frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
524        };
525
526        // update the resource
527        self.r = self_r.update(new_r);
528    }
529
530    /// Delete a single key from the map
531    /// ```
532    /// proof fn delete_key(tracked mut auth: GhostMapAuth<int, int>)
533    ///     requires
534    ///         auth.dom().contains(1int),
535    ///     ensures
536    ///         old(auth)@ == auth@
537    /// {
538    ///     let tracked points_to = auth.insert(1, 1);
539    ///     // do something with the submap
540    ///     auth.delete_points_to(points_to)
541    /// }
542    /// ```
543    pub proof fn delete_points_to(tracked &mut self, tracked p: GhostPointsTo<K, V>)
544        requires
545            p.id() == old(self).id(),
546        ensures
547            self.id() == old(self).id(),
548            self@ == old(self)@.remove(p.key()),
549    {
550        use_type_invariant(&p);
551        p.lemma_map_view();
552        self.delete(p.submap);
553    }
554
555    /// Create a new [`GhostMapAuth`] from a [`Map`].
556    /// Gives the other half of ownership in the form of a [`GhostSubmap`].
557    ///
558    /// ```
559    /// fn example() {
560    ///     let m = map![1int => 1int, 2int => 4int, 3int => 9int];
561    ///     let tracked (auth, sub) = GhostMapAuth::new(m);
562    ///     assert(auth@ == m);
563    ///     assert(sub.dom() == m.dom());
564    /// }
565    /// ```
566    pub proof fn new(m: Map<K, V>) -> (tracked result: (GhostMapAuth<K, V>, GhostSubmap<K, V>))
567        ensures
568            result.0.id() == result.1.id(),
569            result.0@ == m,
570            result.1@ == m,
571    {
572        let tracked full_r = Resource::alloc(
573            MapCarrier {
574                auth: AuthCarrier::Auth(m),
575                frac: FracCarrier::Frac { owning: m, dup: Map::empty() },
576            },
577        );
578
579        let auth_carrier = MapCarrier {
580            auth: AuthCarrier::Auth(m),
581            frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
582        };
583
584        let frac_carrier = MapCarrier {
585            auth: AuthCarrier::Frac,
586            frac: FracCarrier::Frac { owning: m, dup: Map::empty() },
587        };
588
589        assert(full_r.value() == MapCarrier::op(auth_carrier, frac_carrier));
590        let tracked (auth_r, frac_r) = full_r.split(auth_carrier, frac_carrier);
591        (GhostMapAuth { r: auth_r }, GhostSubmap { r: frac_r })
592    }
593}
594
595impl<K, V> GhostSubmap<K, V> {
596    #[verifier::type_invariant]
597    spec fn inv(self) -> bool {
598        &&& self.r.value().auth is Frac
599        &&& self.r.value().frac is Frac
600        &&& self.r.value().frac.dup_map().is_empty()
601    }
602
603    /// Checks whether the [`GhostSubmap`] refers to a single key (and thus can be converted to a
604    /// [`GhostPointsTo`]).
605    pub open spec fn is_points_to(self) -> bool {
606        &&& self@.len() == 1
607        &&& self.dom().finite()
608        &&& !self@.is_empty()
609    }
610
611    /// Resource location
612    pub closed spec fn id(self) -> Loc {
613        self.r.loc()
614    }
615
616    /// Logically underlying [`Map`]
617    pub closed spec fn view(self) -> Map<K, V> {
618        self.r.value().frac.owning_map()
619    }
620
621    /// Domain of the [`GhostSubmap`]
622    pub open spec fn dom(self) -> Set<K> {
623        self@.dom()
624    }
625
626    /// Indexing operation `submap[key]`
627    pub open spec fn spec_index(self, key: K) -> V
628        recommends
629            self.dom().contains(key),
630    {
631        self@[key]
632    }
633
634    /// Instantiate a dummy [`GhostSubmap`]
635    pub proof fn dummy() -> (tracked result: GhostSubmap<K, V>) {
636        let tracked (auth, submap) = GhostMapAuth::<K, V>::new(Map::empty());
637        submap
638    }
639
640    /// Instantiate an empty [`GhostSubmap`] of a particular id
641    pub proof fn empty(id: int) -> (tracked result: GhostSubmap<K, V>)
642        ensures
643            result.id() == id,
644            result@ == Map::<K, V>::empty(),
645    {
646        let tracked r = Resource::create_unit(id);
647        GhostSubmap { r }
648    }
649
650    /// Extract the [`GhostSubmap`] from a mutable reference, leaving behind an empty map.
651    pub proof fn take(tracked &mut self) -> (tracked result: GhostSubmap<K, V>)
652        ensures
653            old(self).id() == self.id(),
654            self@.is_empty(),
655            result == *old(self),
656            result.id() == self.id(),
657    {
658        use_type_invariant(&*self);
659
660        let tracked mut r = Self::empty(self.id());
661        tracked_swap(self, &mut r);
662        r
663    }
664
665    /// Agreement between a [`GhostSubmap`] and a corresponding [`GhostMapAuth`]
666    ///
667    /// Verus might not have full context of the [`GhostMapAuth`] and a corresponding [`GhostSubmap`].
668    /// However, whenever we know that they refer to the same resource (i.e., have matching ids) we
669    /// can assert that the [`GhostSubmap`] is a submap of the [`GhostMapAuth`].
670    /// ```
671    /// proof fn test(tracked &auth: GhostMapAuth<int, int>, tracked &sub: GhostSubmap<int, int>)
672    ///     requires
673    ///         auth.id() == sub.id(),
674    ///         sub.dom().contains(1int),
675    ///         sub[1int] == 1int,
676    ///     ensures
677    ///         auth[1int] == 1int
678    /// {
679    ///     sub.agree(auth);
680    ///     assert(sub@ <= auth@);
681    ///     assert(auth[1int] == 1int);
682    /// }
683    /// ```
684    pub proof fn agree(tracked self: &GhostSubmap<K, V>, tracked auth: &GhostMapAuth<K, V>)
685        requires
686            self.id() == auth.id(),
687        ensures
688            self@ <= auth@,
689    {
690        broadcast use lemma_submap_of_trans;
691
692        use_type_invariant(self);
693        use_type_invariant(auth);
694
695        let tracked joined = self.r.join_shared(&auth.r);
696        joined.validate();
697        assert(self.r.value().frac.owning_map() <= joined.value().frac.owning_map());
698    }
699
700    /// Combining two [`GhostSubmap`]s is possible.
701    /// We consume the input [`GhostSubmap`] and merge it into the first.
702    /// We also learn that they were disjoint.
703    pub proof fn combine(tracked &mut self, tracked other: GhostSubmap<K, V>)
704        requires
705            old(self).id() == other.id(),
706        ensures
707            self.id() == old(self).id(),
708            self@ == old(self)@.union_prefer_right(other@),
709            old(self)@.dom().disjoint(other@.dom()),
710    {
711        use_type_invariant(&*self);
712        use_type_invariant(&other);
713
714        let tracked mut r = Resource::alloc(MapCarrier::unit());
715        tracked_swap(&mut self.r, &mut r);
716        r.validate_2(&other.r);
717        self.r = r.join(other.r);
718    }
719
720    /// Combining a [`GhostPointsTo`] into [`GhostSubmap`] is possible, in a similar way to the way to combine
721    /// [`GhostSubmap`]s.
722    pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPointsTo<K, V>)
723        requires
724            old(self).id() == other.id(),
725        ensures
726            self.id() == old(self).id(),
727            self@ == old(self)@.insert(other.key(), other.value()),
728            !old(self)@.contains_key(other.key()),
729    {
730        use_type_invariant(&*self);
731        use_type_invariant(&other);
732
733        other.lemma_map_view();
734        self.combine(other.submap);
735    }
736
737    /// When we have two [`GhostSubmap`]s we can prove that they have disjoint domains.
738    pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubmap<K, V>)
739        requires
740            old(self).id() == other.id(),
741        ensures
742            self.id() == old(self).id(),
743            self@ == old(self)@,
744            self@.dom().disjoint(other@.dom()),
745    {
746        use_type_invariant(&*self);
747        use_type_invariant(other);
748        self.r.validate_2(&other.r);
749    }
750
751    /// When we have a [`GhostSubmap`] and a [`GhostPersistentSubmap`] we can prove that they are in disjoint
752    /// domains.
753    pub proof fn disjoint_persistent(tracked &mut self, tracked other: &GhostPersistentSubmap<K, V>)
754        requires
755            old(self).id() == other.id(),
756        ensures
757            self.id() == old(self).id(),
758            self@ == old(self)@,
759            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    /// When we have a [`GhostSubmap`] and a [`GhostPointsTo`] we can prove that they are in disjoint
767    /// domains.
768    pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
769        requires
770            old(self).id() == other.id(),
771        ensures
772            self.id() == old(self).id(),
773            self@ == old(self)@,
774            !self@.contains_key(other.key()),
775    {
776        use_type_invariant(&*self);
777        use_type_invariant(other);
778        self.disjoint(&other.submap);
779    }
780
781    /// When we have a [`GhostSubmap`] and a [`GhostPersistentPointsTo`] we can prove that they are in disjoint
782    /// domains.
783    pub proof fn disjoint_persistent_points_to(
784        tracked &mut self,
785        tracked other: &GhostPersistentPointsTo<K, V>,
786    )
787        requires
788            old(self).id() == other.id(),
789        ensures
790            self.id() == old(self).id(),
791            self@ == old(self)@,
792            !self@.contains_key(other.key()),
793    {
794        use_type_invariant(&*self);
795        use_type_invariant(other);
796        self.disjoint_persistent(&other.submap);
797    }
798
799    /// We can split a [`GhostSubmap`] based on a set of keys in its domain.
800    pub proof fn split(tracked &mut self, s: Set<K>) -> (tracked result: GhostSubmap<K, V>)
801        requires
802            s <= old(self)@.dom(),
803        ensures
804            self.id() == old(self).id(),
805            result.id() == self.id(),
806            old(self)@ == self@.union_prefer_right(result@),
807            result@.dom() =~= s,
808            self@.dom() =~= old(self)@.dom() - s,
809    {
810        use_type_invariant(&*self);
811
812        let tracked mut r = Resource::alloc(MapCarrier::<K, V>::unit());
813        tracked_swap(&mut self.r, &mut r);
814
815        let self_carrier = MapCarrier {
816            auth: AuthCarrier::Frac,
817            frac: FracCarrier::Frac {
818                owning: r.value().frac.owning_map().remove_keys(s),
819                dup: r.value().frac.dup_map(),
820            },
821        };
822
823        let res_carrier = MapCarrier {
824            auth: AuthCarrier::Frac,
825            frac: FracCarrier::Frac {
826                owning: r.value().frac.owning_map().restrict(s),
827                dup: r.value().frac.dup_map(),
828            },
829        };
830
831        assert(r.value().frac == MapCarrier::op(self_carrier, res_carrier).frac);
832        let tracked (self_r, res_r) = r.split(self_carrier, res_carrier);
833        self.r = self_r;
834        GhostSubmap { r: res_r }
835    }
836
837    /// We can separate a single key out of a [`GhostSubmap`]
838    pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result: GhostPointsTo<K, V>)
839        requires
840            old(self)@.contains_key(k),
841        ensures
842            self.id() == old(self).id(),
843            result.id() == self.id(),
844            old(self)@ == self@.insert(result.key(), result.value()),
845            result.key() == k,
846            self@.dom() =~= old(self)@.dom().remove(k),
847    {
848        use_type_invariant(&*self);
849
850        let tracked submap = self.split(set![k]);
851        GhostPointsTo { submap }
852    }
853
854    /// When we have both the [`GhostMapAuth`] and a [`GhostSubmap`] we can update the values for a
855    /// subset of keys in our submap.
856    /// ```
857    /// proof fn test(tracked auth: &mut GhostMapAuth<int, int>, tracked sub: &mut GhostSubmap<int, int>)
858    ///     requires
859    ///         auth.id() == sub.id(),
860    ///         sub.dom() == set![1int, 2int, 3int]
861    ///     ensures
862    ///         auth[1int] == 9int
863    ///         auth[2int] == 10int
864    ///         auth[3int] == 11int
865    /// {
866    ///     // need to agree on the subset
867    ///     sub.agree(auth);
868    ///     assert(sub@ <= auth@);
869    ///     sub.update(map![1int => 9int, 2int => 10int, 3int => 11int]);
870    /// }
871    /// ```
872    pub proof fn update(tracked &mut self, tracked auth: &mut GhostMapAuth<K, V>, m: Map<K, V>)
873        requires
874            m.dom() <= old(self)@.dom(),
875            old(self).id() == old(auth).id(),
876        ensures
877            self.id() == old(self).id(),
878            auth.id() == old(auth).id(),
879            self@ == old(self)@.union_prefer_right(m),
880            auth@ == old(auth)@.union_prefer_right(m),
881    {
882        broadcast use lemma_submap_of_trans;
883        broadcast use lemma_submap_of_op;
884
885        use_type_invariant(&*self);
886        use_type_invariant(&*auth);
887
888        let tracked mut mself = Self::dummy();
889        tracked_swap(self, &mut mself);
890        let tracked mut frac_r = mself.r;
891
892        let tracked mut mauth = GhostMapAuth::<K, V>::dummy();
893        tracked_swap(auth, &mut mauth);
894        let tracked mut auth_r = mauth.r;
895
896        frac_r.validate_2(&auth_r);
897        let tracked mut full_r = frac_r.join(auth_r);
898
899        assert(full_r.value().frac.owning_map() == frac_r.value().frac.owning_map());
900
901        let auth_carrier = AuthCarrier::Auth(full_r.value().auth.map().union_prefer_right(m));
902        let frac_carrier = FracCarrier::Frac {
903            owning: full_r.value().frac.owning_map().union_prefer_right(m),
904            dup: Map::empty(),
905        };
906        let new_full_carrier = MapCarrier { auth: auth_carrier, frac: frac_carrier };
907
908        assert(new_full_carrier.valid());
909        let tracked r_upd = full_r.update(new_full_carrier);
910
911        let new_auth_carrier = MapCarrier {
912            auth: r_upd.value().auth,
913            frac: FracCarrier::Frac { owning: Map::empty(), dup: Map::empty() },
914        };
915        let new_frac_carrier = MapCarrier { auth: AuthCarrier::Frac, frac: r_upd.value().frac };
916        assert(r_upd.value().frac == MapCarrier::op(new_auth_carrier, new_frac_carrier).frac);
917        assert(r_upd.value() == MapCarrier::op(new_auth_carrier, new_frac_carrier));
918
919        let tracked (new_auth_r, new_frac_r) = r_upd.split(new_auth_carrier, new_frac_carrier);
920        auth.r = new_auth_r;
921        self.r = new_frac_r;
922    }
923
924    /// Converting a [`GhostSubmap`] into a [`GhostPointsTo`]
925    pub proof fn points_to(tracked self) -> (tracked r: GhostPointsTo<K, V>)
926        requires
927            self.is_points_to(),
928        ensures
929            self@ == map![r.key() => r.value()],
930            self.id() == r.id(),
931    {
932        let tracked r = GhostPointsTo { submap: self };
933        r.lemma_map_view();
934        r
935    }
936
937    /// Convert a [`GhostSubmap`] into a [`GhostPersistentSubmap`]
938    pub proof fn persist(tracked self) -> (tracked r: GhostPersistentSubmap<K, V>)
939        ensures
940            self@ == r@,
941            self.id() == r.id(),
942    {
943        broadcast use lemma_submap_of_trans;
944        broadcast use lemma_submap_of_op;
945
946        use_type_invariant(&self);
947
948        let tracked mut r = self.r;
949
950        let self_carrier = MapCarrier {
951            auth: AuthCarrier::Frac,
952            frac: FracCarrier::Frac {
953                owning: self.r.value().frac.owning_map(),
954                dup: self.r.value().frac.dup_map(),
955            },
956        };
957
958        let res_carrier = MapCarrier {
959            auth: AuthCarrier::Frac,
960            frac: FracCarrier::Frac {
961                owning: self.r.value().frac.dup_map(),
962                dup: self.r.value().frac.owning_map(),
963            },
964        };
965
966        let tracked r = r.update(res_carrier);
967        GhostPersistentSubmap { r }
968    }
969}
970
971impl<K, V> GhostPersistentSubmap<K, V> {
972    #[verifier::type_invariant]
973    spec fn inv(self) -> bool {
974        &&& self.r.value().auth is Frac
975        &&& self.r.value().frac is Frac
976        &&& self.r.value().frac.owning_map().is_empty()
977    }
978
979    /// Checks whether the [`GhostPersistentSubmap`] refers to a single key (and thus can be converted to a
980    /// [`GhostPersistentPointsTo`]).
981    pub open spec fn is_points_to(self) -> bool {
982        &&& self@.len() == 1
983        &&& self.dom().finite()
984        &&& !self@.is_empty()
985    }
986
987    /// Resource location
988    pub closed spec fn id(self) -> Loc {
989        self.r.loc()
990    }
991
992    /// Logically underlying [`Map`]
993    pub closed spec fn view(self) -> Map<K, V> {
994        self.r.value().frac.dup_map()
995    }
996
997    /// Domain of the [`GhostPersistentSubmap`]
998    pub open spec fn dom(self) -> Set<K> {
999        self@.dom()
1000    }
1001
1002    /// Indexing operation `submap[key]`
1003    pub open spec fn spec_index(self, key: K) -> V
1004        recommends
1005            self.dom().contains(key),
1006    {
1007        self@[key]
1008    }
1009
1010    /// Instantiate a dummy [`GhostPersistentSubmap`]
1011    pub proof fn dummy() -> (tracked result: GhostPersistentSubmap<K, V>) {
1012        let tracked owned = GhostSubmap::<K, V>::dummy();
1013        owned.persist()
1014    }
1015
1016    /// Instantiate an empty [`GhostPersistentSubmap`] of a particular id
1017    pub proof fn empty(id: int) -> (tracked result: GhostPersistentSubmap<K, V>)
1018        ensures
1019            result.id() == id,
1020            result@ == Map::<K, V>::empty(),
1021    {
1022        let tracked r = Resource::create_unit(id);
1023        GhostPersistentSubmap { r }
1024    }
1025
1026    /// Duplicate the [`GhostPersistentSubmap`]
1027    pub proof fn duplicate(tracked &mut self) -> (tracked result: GhostPersistentSubmap<K, V>)
1028        ensures
1029            self.id() == result.id(),
1030            old(self).id() == self.id(),
1031            old(self)@ == self@,
1032            result@ == self@,
1033    {
1034        use_type_invariant(&*self);
1035
1036        let tracked mut owned = Self::empty(self.id());
1037        let carrier = self.r.value();
1038        assert(carrier == MapCarrier::op(carrier, carrier));
1039
1040        tracked_swap(self, &mut owned);
1041        let tracked (mut orig, new) = owned.r.split(carrier, carrier);
1042        tracked_swap(&mut self.r, &mut orig);
1043        GhostPersistentSubmap { r: new }
1044    }
1045
1046    /// Agreement between a [`GhostPersistentSubmap`] and a corresponding [`GhostMapAuth`]
1047    ///
1048    /// Verus might not have full context of the [`GhostMapAuth`] and a corresponding [`GhostPersistentSubmap`].
1049    /// However, whenever we know that they refer to the same resource (i.e., have matching ids) we
1050    /// can assert that the [`GhostPersistentSubmap`] is a submap of the [`GhostMapAuth`].
1051    /// ```
1052    /// proof fn test(tracked &auth: GhostMapAuth<int, int>, tracked &sub: GhostPersistentSubmap<int, int>)
1053    ///     requires
1054    ///         auth.id() == sub.id(),
1055    ///         sub.dom().contains(1int),
1056    ///         sub[1int] == 1int,
1057    ///     ensures
1058    ///         auth[1int] == 1int
1059    /// {
1060    ///     sub.agree(auth);
1061    ///     assert(sub@ <= auth@);
1062    ///     assert(auth[1int] == 1int);
1063    /// }
1064    /// ```
1065    pub proof fn agree(
1066        tracked self: &GhostPersistentSubmap<K, V>,
1067        tracked auth: &GhostMapAuth<K, V>,
1068    )
1069        requires
1070            self.id() == auth.id(),
1071        ensures
1072            self@ <= auth@,
1073    {
1074        broadcast use lemma_submap_of_trans;
1075
1076        use_type_invariant(self);
1077        use_type_invariant(auth);
1078
1079        let tracked joined = self.r.join_shared(&auth.r);
1080        joined.validate();
1081        assert(self.r.value().frac.dup_map() <= joined.value().frac.dup_map());
1082    }
1083
1084    /// Combining two [`GhostPersistentSubmap`]s is possible.
1085    /// We consume the input [`GhostPersistentSubmap`] and merge it into the first.
1086    /// We also learn that they agreed
1087    pub proof fn combine(tracked &mut self, tracked other: GhostPersistentSubmap<K, V>)
1088        requires
1089            old(self).id() == other.id(),
1090        ensures
1091            self.id() == old(self).id(),
1092            self@ == old(self)@.union_prefer_right(other@),
1093            old(self)@.agrees(other@),
1094    {
1095        use_type_invariant(&*self);
1096        use_type_invariant(&other);
1097
1098        let tracked mut r = Resource::alloc(MapCarrier::unit());
1099        tracked_swap(&mut self.r, &mut r);
1100        r.validate_2(&other.r);
1101        self.r = r.join(other.r);
1102    }
1103
1104    /// Combining a [`GhostPersistentPointsTo`] into [`GhostPersistentSubmap`] is possible, in a similar way to the way to combine
1105    /// [`GhostPersistentSubmap`]s.
1106    pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPersistentPointsTo<K, V>)
1107        requires
1108            old(self).id() == other.id(),
1109        ensures
1110            self.id() == old(self).id(),
1111            self@ == old(self)@.insert(other.key(), other.value()),
1112            old(self)@.contains_key(other.key()) ==> old(self)@[other.key()] == other.value(),
1113    {
1114        use_type_invariant(&*self);
1115        use_type_invariant(&other);
1116
1117        other.lemma_map_view();
1118        self.combine(other.submap);
1119    }
1120
1121    /// When we have a [`GhostPersistentSubmap`] and a [`GhostSubmap`] we can prove that they have disjoint domains.
1122    pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1123        requires
1124            old(self).id() == other.id(),
1125        ensures
1126            self.id() == old(self).id(),
1127            self@ == old(self)@,
1128            self@.dom().disjoint(other@.dom()),
1129    {
1130        use_type_invariant(&*self);
1131        use_type_invariant(other);
1132        self.r.validate_2(&other.r);
1133    }
1134
1135    /// When we have two [`GhostPersistentSubmap`]s we can prove that they agree on their intersection.
1136    pub proof fn intersection_agrees(tracked &mut self, tracked other: &GhostPersistentSubmap<K, V>)
1137        requires
1138            old(self).id() == other.id(),
1139        ensures
1140            self.id() == old(self).id(),
1141            self@ == old(self)@,
1142            self@.agrees(other@),
1143    {
1144        use_type_invariant(&*self);
1145        use_type_invariant(other);
1146        self.r.validate_2(&other.r);
1147    }
1148
1149    /// When we have a [`GhostPersistentSubmap`] and a [`GhostPointsTo`] we can prove that they are in disjoint
1150    /// domains.
1151    pub proof fn disjoint_points_to(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1152        requires
1153            old(self).id() == other.id(),
1154        ensures
1155            self.id() == old(self).id(),
1156            self@ == old(self)@,
1157            !self@.contains_key(other.key()),
1158    {
1159        use_type_invariant(&*self);
1160        use_type_invariant(other);
1161        self.disjoint(&other.submap);
1162    }
1163
1164    /// When we have a [`GhostPersistentSubmap`] and a [`GhostPersistentPointsTo`],
1165    /// we can prove that either they are disjoint domains or the key-value pair is in the
1166    /// persistent submap.
1167    pub proof fn intersection_agrees_points_to(
1168        tracked &mut self,
1169        tracked other: &GhostPersistentPointsTo<K, V>,
1170    )
1171        requires
1172            old(self).id() == other.id(),
1173        ensures
1174            self.id() == old(self).id(),
1175            self@ == old(self)@,
1176            self@.contains_key(other.key()) ==> self@[other.key()] == other.value(),
1177    {
1178        use_type_invariant(&*self);
1179        use_type_invariant(other);
1180        self.intersection_agrees(&other.submap);
1181    }
1182
1183    /// We can split a [`GhostPersistentSubmap`] based on a set of keys in its domain.
1184    pub proof fn split(tracked &mut self, s: Set<K>) -> (tracked result: GhostPersistentSubmap<
1185        K,
1186        V,
1187    >)
1188        requires
1189            s <= old(self)@.dom(),
1190        ensures
1191            self.id() == old(self).id(),
1192            result.id() == self.id(),
1193            old(self)@ == self@.union_prefer_right(result@),
1194            result@.dom() =~= s,
1195            self@.dom() =~= old(self)@.dom() - s,
1196    {
1197        use_type_invariant(&*self);
1198
1199        let tracked mut r = Resource::alloc(MapCarrier::<K, V>::unit());
1200        tracked_swap(&mut self.r, &mut r);
1201
1202        let self_carrier = MapCarrier {
1203            auth: AuthCarrier::Frac,
1204            frac: FracCarrier::Frac {
1205                owning: r.value().frac.owning_map(),
1206                dup: r.value().frac.dup_map().remove_keys(s),
1207            },
1208        };
1209
1210        let res_carrier = MapCarrier {
1211            auth: AuthCarrier::Frac,
1212            frac: FracCarrier::Frac {
1213                owning: r.value().frac.owning_map(),
1214                dup: r.value().frac.dup_map().restrict(s),
1215            },
1216        };
1217
1218        assert(r.value().frac == MapCarrier::op(self_carrier, res_carrier).frac);
1219        let tracked (self_r, res_r) = r.split(self_carrier, res_carrier);
1220        self.r = self_r;
1221        GhostPersistentSubmap { r: res_r }
1222    }
1223
1224    /// We can separate a single key out of a [`GhostPersistentSubmap`]
1225    pub proof fn split_points_to(tracked &mut self, k: K) -> (tracked result:
1226        GhostPersistentPointsTo<K, V>)
1227        requires
1228            old(self)@.contains_key(k),
1229        ensures
1230            self.id() == old(self).id(),
1231            result.id() == self.id(),
1232            old(self)@ == self@.insert(result.key(), result.value()),
1233            result.key() == k,
1234            self@.dom() =~= old(self)@.dom().remove(k),
1235    {
1236        use_type_invariant(&*self);
1237
1238        let tracked submap = self.split(set![k]);
1239        GhostPersistentPointsTo { submap }
1240    }
1241
1242    /// Convert a [`GhostPersistentSubmap`] into a [`GhostPersistentPointsTo`]
1243    pub proof fn points_to(tracked self) -> (tracked r: GhostPersistentPointsTo<K, V>)
1244        requires
1245            self.is_points_to(),
1246        ensures
1247            self@ == map![r.key() => r.value()],
1248            self.id() == r.id(),
1249    {
1250        let tracked r = GhostPersistentPointsTo { submap: self };
1251        r.lemma_map_view();
1252        r
1253    }
1254}
1255
1256impl<K, V> GhostPointsTo<K, V> {
1257    #[verifier::type_invariant]
1258    spec fn inv(self) -> bool {
1259        self.submap.is_points_to()
1260    }
1261
1262    /// Location of the underlying resource
1263    pub closed spec fn id(self) -> Loc {
1264        self.submap.id()
1265    }
1266
1267    /// Key-Value pair underlying the points to relationship
1268    pub open spec fn view(self) -> (K, V) {
1269        (self.key(), self.value())
1270    }
1271
1272    /// Key of the points to
1273    pub closed spec fn key(self) -> K {
1274        self.submap.dom().choose()
1275    }
1276
1277    /// Pointed-to value
1278    pub closed spec fn value(self) -> V {
1279        self.submap[self.key()]
1280    }
1281
1282    /// Agreement between a [`GhostPointsTo`] and a corresponding [`GhostMapAuth`]
1283    ///
1284    /// Verus might not have full context of the [`GhostMapAuth`] and a corresponding [`GhostPointsTo`].
1285    /// However, whenever we know that they refer to the same resource (i.e., have matching ids) we
1286    /// can assert that the [`GhostPointsTo`] is a key-value pair in the [`GhostMapAuth`].
1287    /// ```
1288    /// proof fn test(tracked &auth: GhostMapAuth<int, int>, tracked &pt: GhostPointsTo<int, int>)
1289    ///     requires
1290    ///         auth.id() == sub.id(),
1291    ///         pt@ == (1int, 1int)
1292    ///     ensures
1293    ///         auth[1int] == 1int
1294    /// {
1295    ///     pt.agree(auth);
1296    ///     assert(auth[1int] == 1int);
1297    /// }
1298    /// ```
1299    pub proof fn agree(tracked self: &GhostPointsTo<K, V>, tracked auth: &GhostMapAuth<K, V>)
1300        requires
1301            self.id() == auth.id(),
1302        ensures
1303            auth@.contains_pair(self.key(), self.value()),
1304    {
1305        use_type_invariant(self);
1306        use_type_invariant(auth);
1307
1308        self.lemma_map_view();
1309        self.submap.agree(auth);
1310        assert(self.submap@ <= auth@);
1311        assert(self.submap@.contains_key(self.key()));
1312        assert(self.submap@.contains_pair(self.key(), self.value()));
1313    }
1314
1315    /// We can combine two [`GhostPointsTo`]s into a [`GhostSubmap`]
1316    /// We also learn that they were disjoint.
1317    pub proof fn combine(tracked self, tracked other: GhostPointsTo<K, V>) -> (tracked r:
1318        GhostSubmap<K, V>)
1319        requires
1320            self.id() == other.id(),
1321        ensures
1322            r.id() == self.id(),
1323            r@ == map![self.key() => self.value(), other.key() => other.value()],
1324            self.key() != other.key(),
1325    {
1326        use_type_invariant(&self);
1327        use_type_invariant(&other);
1328
1329        let tracked mut submap = self.submap();
1330        submap.combine_points_to(other);
1331
1332        submap
1333    }
1334
1335    /// Shows that if a two [`GhostPointsTo`]s are not owning the same key
1336    pub proof fn disjoint(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1337        requires
1338            old(self).id() == other.id(),
1339        ensures
1340            self.id() == old(self).id(),
1341            self@ == old(self)@,
1342            self.key() != other.key(),
1343    {
1344        use_type_invariant(&*self);
1345        use_type_invariant(other);
1346        self.submap.disjoint(&other.submap);
1347    }
1348
1349    /// Shows that if a [`GhostPointsTo`] and a [`GhostSubmap`] are not owning the same key
1350    pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1351        requires
1352            old(self).id() == other.id(),
1353        ensures
1354            self.id() == old(self).id(),
1355            self@ == old(self)@,
1356            !other.dom().contains(self.key()),
1357    {
1358        use_type_invariant(&*self);
1359        use_type_invariant(other);
1360        self.submap.disjoint(other);
1361    }
1362
1363    /// Shows that if a [`GhostPointsTo`] and a [`GhostPersistentSubmap`] are not owning the same key
1364    pub proof fn disjoint_persistent_submap(
1365        tracked &mut self,
1366        tracked other: &GhostPersistentSubmap<K, V>,
1367    )
1368        requires
1369            old(self).id() == other.id(),
1370        ensures
1371            self.id() == old(self).id(),
1372            self@ == old(self)@,
1373            !other.dom().contains(self.key()),
1374    {
1375        use_type_invariant(&*self);
1376        use_type_invariant(other);
1377        self.submap.disjoint_persistent(other);
1378    }
1379
1380    /// Shows that if a [`GhostPointsTo`] and a [`GhostPersistentPointsTo`] are not owning the same key
1381    pub proof fn disjoint_persistent(
1382        tracked &mut self,
1383        tracked other: &GhostPersistentPointsTo<K, V>,
1384    )
1385        requires
1386            old(self).id() == other.id(),
1387        ensures
1388            self.id() == old(self).id(),
1389            self@ == old(self)@,
1390            self.key() != other.key(),
1391    {
1392        use_type_invariant(&*self);
1393        use_type_invariant(other);
1394        self.submap.disjoint_persistent_points_to(other);
1395    }
1396
1397    /// Update pointed to value
1398    pub proof fn update(tracked &mut self, tracked auth: &mut GhostMapAuth<K, V>, v: V)
1399        requires
1400            old(self).id() == old(auth).id(),
1401        ensures
1402            self.id() == old(self).id(),
1403            auth.id() == old(auth).id(),
1404            self.key() == old(self).key(),
1405            self@ == (self.key(), v),
1406            auth@ == old(auth)@.union_prefer_right(map![self.key() => v]),
1407    {
1408        broadcast use lemma_submap_of_trans;
1409        broadcast use lemma_submap_of_op;
1410
1411        use_type_invariant(&*self);
1412        use_type_invariant(&*auth);
1413
1414        let ghost old_dom = self.submap.dom();
1415        self.lemma_map_view();
1416        let m = map![self.key() => v];
1417        assert(self.submap@.union_prefer_right(m) == m);
1418        self.submap.update(auth, m);
1419    }
1420
1421    /// Convert the [`GhostPointsTo`] a [`GhostSubmap`]
1422    pub proof fn submap(tracked self) -> (tracked r: GhostSubmap<K, V>)
1423        ensures
1424            r.id() == self.id(),
1425            r@ == map![self.key() => self.value()],
1426    {
1427        self.lemma_map_view();
1428        self.submap
1429    }
1430
1431    proof fn lemma_map_view(tracked &self)
1432        ensures
1433            self.submap@ == map![self.key() => self.value()],
1434    {
1435        use_type_invariant(self);
1436        let key = self.key();
1437        let target_dom = set![key];
1438
1439        assert(self.submap@.dom().len() == 1);
1440        assert(target_dom.len() == 1);
1441
1442        assert(self.submap@.dom().finite());
1443        assert(target_dom.finite());
1444
1445        assert(self.submap@.dom().contains(key));
1446        assert(target_dom.contains(key));
1447
1448        assert(self.submap@.dom().remove(key).len() == 0);
1449        assert(target_dom.remove(key).len() == 0);
1450
1451        assert(self.submap@.dom() =~= target_dom);
1452        assert(self.submap@ == map![self.key() => self.value()]);
1453    }
1454
1455    /// Can be used to learn what the key-value pair of [`GhostPointsTo`] is
1456    pub proof fn lemma_view(self)
1457        ensures
1458            self@ == (self.key(), self.value()),
1459    {
1460    }
1461
1462    /// Convert a [`GhostPointsTo`] into a [`GhostPersistentPointsTo`]
1463    pub proof fn persist(tracked self) -> (tracked r: GhostPersistentPointsTo<K, V>)
1464        ensures
1465            self@ == r@,
1466            self.id() == r.id(),
1467    {
1468        use_type_invariant(&self);
1469        self.submap.persist().points_to()
1470    }
1471}
1472
1473impl<K, V> GhostPersistentPointsTo<K, V> {
1474    #[verifier::type_invariant]
1475    spec fn inv(self) -> bool {
1476        self.submap.is_points_to()
1477    }
1478
1479    /// Location of the underlying resource
1480    pub closed spec fn id(self) -> Loc {
1481        self.submap.id()
1482    }
1483
1484    /// Key-Value pair underlying the points to relationship
1485    pub open spec fn view(self) -> (K, V) {
1486        (self.key(), self.value())
1487    }
1488
1489    /// Key of the points to
1490    pub closed spec fn key(self) -> K {
1491        self.submap.dom().choose()
1492    }
1493
1494    /// Pointed-to value
1495    pub closed spec fn value(self) -> V {
1496        self.submap[self.key()]
1497    }
1498
1499    /// Duplicate the [`GhostPersistentPointsTo`]
1500    pub proof fn duplicate(tracked &mut self) -> (tracked result: GhostPersistentPointsTo<K, V>)
1501        ensures
1502            self.id() == result.id(),
1503            old(self).id() == self.id(),
1504            old(self)@ == self@,
1505            result@ == self@,
1506    {
1507        use_type_invariant(&*self);
1508        let tracked submap = self.submap.duplicate();
1509        GhostPersistentPointsTo { submap }
1510    }
1511
1512    /// Agreement between a [`GhostPersistentPointsTo`] and a corresponding [`GhostMapAuth`]
1513    ///
1514    /// Verus might not have full context of the [`GhostMapAuth`] and a corresponding [`GhostPersistentPointsTo`].
1515    /// However, whenever we know that they refer to the same resource (i.e., have matching ids) we
1516    /// can assert that the [`GhostPersistentPointsTo`] is a key-value pair in the [`GhostMapAuth`].
1517    /// ```
1518    /// proof fn test(tracked &auth: GhostMapAuth<int, int>, tracked &pt: GhostPersistentPointsTo<int, int>)
1519    ///     requires
1520    ///         auth.id() == sub.id(),
1521    ///         pt@ == (1int, 1int)
1522    ///     ensures
1523    ///         auth[1int] == 1int
1524    /// {
1525    ///     pt.agree(auth);
1526    ///     assert(auth[1int] == 1int);
1527    /// }
1528    /// ```
1529    pub proof fn agree(
1530        tracked self: &GhostPersistentPointsTo<K, V>,
1531        tracked auth: &GhostMapAuth<K, V>,
1532    )
1533        requires
1534            self.id() == auth.id(),
1535        ensures
1536            auth@.contains_pair(self.key(), self.value()),
1537    {
1538        use_type_invariant(self);
1539        use_type_invariant(auth);
1540
1541        self.lemma_map_view();
1542        self.submap.agree(auth);
1543        assert(self.submap@ <= auth@);
1544        assert(self.submap@.contains_key(self.key()));
1545    }
1546
1547    /// We can combine two [`GhostPersistentPointsTo`]s into a [`GhostPersistentSubmap`]
1548    pub proof fn combine(
1549        tracked self,
1550        tracked other: GhostPersistentPointsTo<K, V>,
1551    ) -> (tracked submap: GhostPersistentSubmap<K, V>)
1552        requires
1553            self.id() == other.id(),
1554        ensures
1555            submap.id() == self.id(),
1556            submap@ == map![self.key() => self.value(), other.key() => other.value()],
1557            self.key() != other.key() ==> submap@.len() == 2,
1558            self.key() == other.key() ==> submap@.len() == 1,
1559    {
1560        use_type_invariant(&self);
1561        use_type_invariant(&other);
1562
1563        let tracked mut submap = self.submap();
1564        submap.combine_points_to(other);
1565
1566        submap
1567    }
1568
1569    /// When we have a [`GhostPersistentPointsTo`] and a [`GhostPointsTo`], we can prove that they are in disjoint
1570    /// domains.
1571    pub proof fn disjoint(tracked &mut self, tracked other: &GhostPointsTo<K, V>)
1572        requires
1573            old(self).id() == other.id(),
1574        ensures
1575            self.id() == old(self).id(),
1576            self@ == old(self)@,
1577            self.key() != other.key(),
1578    {
1579        use_type_invariant(&*self);
1580        use_type_invariant(other);
1581        self.disjoint_submap(&other.submap);
1582    }
1583
1584    /// When we have a [`GhostPersistentPointsTo`] and a [`GhostSubmap`], we can prove that they are in disjoint
1585    /// domains.
1586    pub proof fn disjoint_submap(tracked &mut self, tracked other: &GhostSubmap<K, V>)
1587        requires
1588            old(self).id() == other.id(),
1589        ensures
1590            self.id() == old(self).id(),
1591            self@ == old(self)@,
1592            !other@.contains_key(self.key()),
1593    {
1594        use_type_invariant(&*self);
1595        use_type_invariant(other);
1596        self.submap.disjoint(&other);
1597    }
1598
1599    /// Shows that if a client has two [`GhostPersistentPointsTo`]s they are either disjoint or
1600    /// agreeing in values in the intersection
1601    pub proof fn intersection_agrees(
1602        tracked &mut self,
1603        tracked other: &GhostPersistentPointsTo<K, V>,
1604    )
1605        requires
1606            old(self).id() == other.id(),
1607        ensures
1608            self.id() == old(self).id(),
1609            self@ == old(self)@,
1610            self.key() == other.key() ==> self.value() == other.value(),
1611    {
1612        use_type_invariant(&*self);
1613        use_type_invariant(other);
1614        self.submap.intersection_agrees_points_to(&other);
1615    }
1616
1617    /// Shows that if a [`GhostPersistentPointsTo`] and a [`GhostSubmap`] are not owning the same key
1618    pub proof fn intersection_agrees_submap(
1619        tracked &mut self,
1620        tracked other: &GhostPersistentSubmap<K, V>,
1621    )
1622        requires
1623            old(self).id() == other.id(),
1624        ensures
1625            self.id() == old(self).id(),
1626            self@ == old(self)@,
1627            other@.contains_key(self.key()) ==> other@[self.key()] == self.value(),
1628    {
1629        use_type_invariant(&*self);
1630        use_type_invariant(other);
1631        self.submap.intersection_agrees(other);
1632    }
1633
1634    /// Convert the [`GhostPersistentPointsTo`] a [`GhostPersistentSubmap`]
1635    pub proof fn submap(tracked self) -> (tracked r: GhostPersistentSubmap<K, V>)
1636        ensures
1637            r.id() == self.id(),
1638            r@ == map![self.key() => self.value()],
1639    {
1640        self.lemma_map_view();
1641        self.submap
1642    }
1643
1644    proof fn lemma_map_view(tracked &self)
1645        ensures
1646            self.submap@ == map![self.key() => self.value()],
1647    {
1648        use_type_invariant(self);
1649        let key = self.key();
1650        let target_dom = set![key];
1651
1652        assert(self.submap@.dom().len() == 1);
1653        assert(target_dom.len() == 1);
1654
1655        assert(self.submap@.dom().finite());
1656        assert(target_dom.finite());
1657
1658        assert(self.submap@.dom().contains(key));
1659        assert(target_dom.contains(key));
1660
1661        assert(self.submap@.dom().remove(key).len() == 0);
1662        assert(target_dom.remove(key).len() == 0);
1663
1664        assert(self.submap@.dom() =~= target_dom);
1665        assert(self.submap@ == map![self.key() => self.value()]);
1666    }
1667
1668    /// Can be used to learn what the key-value pair of [`GhostPersistentPointsTo`] is
1669    pub proof fn lemma_view(self)
1670        ensures
1671            self@ == (self.key(), self.value()),
1672    {
1673    }
1674}
1675
1676} // verus!