Skip to main content

vstd/
map_lib.rs

1#[macro_use]
2use super::map::{Map, assert_maps_equal, assert_maps_equal_internal};
3#[allow(unused_imports)]
4use super::pervasive::*;
5#[allow(unused_imports)]
6use super::prelude::*;
7#[allow(unused_imports)]
8use super::relations::*;
9use super::set::*;
10#[cfg(verus_keep_ghost)]
11use super::set_lib::*;
12
13verus! {
14
15broadcast use {
16    super::map::group_map_lemmas,
17    super::set::group_set_lemmas,
18    super::set_lib::group_set_lib_default,
19    super::iset::group_iset_lemmas,
20};
21
22impl<K, V> Map<K, V> {
23    /// Is `true` if called by a "full" map, i.e., a map containing every element of type `A`.
24    #[verifier::inline]
25    pub open spec fn is_full(self) -> bool {
26        forall|k: K| self.dom().contains(k)
27    }
28
29    /// Is `true` if called by an "empty" map, i.e., a map containing no elements and has length 0
30    #[verifier::inline]
31    pub open spec fn is_empty(self) -> (b: bool) {
32        self.dom().is_empty()
33    }
34
35    /// Returns true if the key `k` is in the domain of `self`.
36    #[verifier::inline]
37    pub open spec fn contains_key(self, k: K) -> bool {
38        self.dom().contains(k)
39    }
40
41    /// Returns true if the value `v` is in the range of `self`.
42    pub open spec fn contains_value(self, v: V) -> bool {
43        exists|i: K| #[trigger] self.dom().contains(i) && self[i] == v
44    }
45
46    /// Returns `Some(v)` if the key `k` is in the domain of `self` and maps to `v`,
47    /// and `None` if the key `k` is not in the domain of `self`.
48    pub open spec fn index_opt(self, k: K) -> Option<V> {
49        if self.contains_key(k) {
50            Some(self[k])
51        } else {
52            None
53        }
54    }
55
56    ///
57    /// Returns the set of values in the map.
58    ///
59    /// ## Example
60    ///
61    /// ```rust
62    /// let m: Map<int, int> = map![1 => 10, 2 => 11];
63    /// assert(m.values() == set![10int, 11int]) by {
64    ///     assert(m.contains_key(1));
65    ///     assert(m.contains_key(2));
66    ///     assert(m.values() =~= set![10int, 11int]);
67    /// }
68    /// ```
69    pub open spec fn values(self) -> Set<V> {
70        self.dom().map(|k: K| self[k])
71    }
72
73    ///
74    /// Returns the set of key-value pairs representing the map
75    ///
76    /// ## Example
77    ///
78    /// ```rust
79    /// let m: Map<int, int> = map![1 => 10, 2 => 11];
80    /// assert(m.kv_pairs() == set![(1int, 10int), (2int, 11int)] by {
81    ///     assert(m.contains_pair(1int, 10int));
82    ///     assert(m.contains_pair(2int, 11int));
83    ///     assert(m.kv_pairs() =~= set![(1int, 10int), (2int, 11int)]);
84    /// }
85    /// ```
86    pub open spec fn kv_pairs(self) -> Set<(K, V)> {
87        self.dom().map(|k: K| (k, self[k]))
88    }
89
90    /// Returns true if the key `k` is in the domain of `self`, and it maps to the value `v`.
91    pub open spec fn contains_pair(self, k: K, v: V) -> bool {
92        // We use the implication below to make sure that the solver tries to prove
93        // `self.dom().contains(k)` first. That fact is sometimes necessary to trigger
94        // a quantifier helpful in proving `self[k] == v`.
95        &&& self.dom().contains(k)
96        &&& self.dom().contains(k) ==> self[k] == v
97    }
98
99    /// Returns true if `m1` is _contained in_ `m2`, i.e., the domain of `m1` is a subset
100    /// of the domain of `m2`, and they agree on all values in `m1`.
101    ///
102    /// ## Example
103    ///
104    /// ```rust
105    /// assert(
106    ///    map![1 => 10, 2 => 11].le(map![1 => 10, 2 => 11, 3 => 12])
107    /// );
108    /// ```
109    pub open spec fn submap_of(self, m2: Self) -> bool {
110        forall|k: K| #[trigger]
111            self.dom().contains(k) ==> #[trigger] m2.dom().contains(k) && self[k] == m2[k]
112    }
113
114    #[verifier::inline]
115    pub open spec fn spec_le(self, m2: Self) -> bool {
116        self.submap_of(m2)
117    }
118
119    /// Gives the union of two maps, defined as:
120    ///  * The domain is the union of the two input maps.
121    ///  * For a given key in _both_ input maps, it maps to the same value that it maps to in the _right_ map (`m2`).
122    ///  * For any other key in either input map (but not both), it maps to the same value
123    ///    as it does in that map.
124    ///
125    /// ## Example
126    ///
127    /// ```rust
128    /// assert(
129    ///    map![1 => 10, 2 => 11].union_prefer_right(map![1 => 20, 3 => 13])
130    ///    =~= map![1 => 20, 2 => 11, 3 => 13]);
131    /// ```
132    pub open spec fn union_prefer_right(self, m2: Self) -> Self {
133        Self::new(
134            self.dom().union(m2.dom()),
135            |k: K|
136                if m2.dom().contains(k) {
137                    m2[k]
138                } else {
139                    self[k]
140                },
141        )
142    }
143
144    /// Removes the given keys and their associated values from the map.
145    ///
146    /// Ignores any key in `keys` which is not in the domain of `self`.
147    ///
148    /// ## Example
149    ///
150    /// ```rust
151    /// assert(
152    ///    map![1 => 10, 2 => 11, 3 => 12].remove_keys(set!{2, 3, 4})
153    ///    =~= map![1 => 10]);
154    /// ```
155    pub open spec fn remove_keys(self, keys: Set<K>) -> Self {
156        Self::new(self.dom().difference(keys), |k: K| self[k])
157    }
158
159    /// Complement to `remove_keys`. Restricts the map to (key, value) pairs
160    /// for keys that are _in_ the given set; that is, it removes any keys
161    /// _not_ in the set.
162    ///
163    /// ## Example
164    ///
165    /// ```rust
166    /// assert(
167    ///    map![1 => 10, 2 => 11, 3 => 12].remove_keys(set!{2, 3, 4})
168    ///    =~= map![2 => 11, 3 => 12]);
169    /// ```
170    pub open spec fn restrict(self, keys: Set<K>) -> Self {
171        Self::new(self.dom().intersect(keys), |k: K| self[k])
172    }
173
174    /// Returns `true` if and only if the given key maps to the same value or does not exist in self and m2.
175    pub open spec fn is_equal_on_key(self, m2: Self, key: K) -> bool {
176        ||| (!self.dom().contains(key) && !m2.dom().contains(key))
177        ||| (self.dom().contains(key) && m2.dom().contains(key) && self[key] == m2[key])
178    }
179
180    /// Returns `true` if the two given maps agree on all keys that their domains share
181    pub open spec fn agrees(self, m2: Self) -> bool {
182        forall|k| #![auto] self.dom().contains(k) && m2.dom().contains(k) ==> self[k] == m2[k]
183    }
184
185    /// Map a function `f` over all (k, v) pairs in `self`.
186    pub open spec fn map_entries<W>(self, f: spec_fn(K, V) -> W) -> Map<K, W> {
187        Map::<K, W>::new(self.dom(), |k: K| f(k, self[k]))
188    }
189
190    /// Map a function `f` over the values in `self`.
191    pub open spec fn map_values<W>(self, f: spec_fn(V) -> W) -> Map<K, W> {
192        Map::<K, W>::new(self.dom(), |k: K| f(self[k]))
193    }
194
195    /// Returns `true` if and only if a map is injective
196    pub open spec fn is_injective(self) -> bool {
197        forall|x: K, y: K|
198            x != y && self.dom().contains(x) && self.dom().contains(y) ==> #[trigger] self[x]
199                != #[trigger] self[y]
200    }
201
202    /// Swaps map keys and values. Values are not required to be unique; no
203    /// promises on which key is chosen on the intersection.
204    pub open spec fn invert(self) -> Map<V, K> {
205        Map::<V, K>::new(self.values(), |v: V| choose|k: K| self.contains_pair(k, v))
206    }
207
208    // Proven lemmas
209    /// Removing a key from a map that previously contained that key decreases
210    /// the map's length by one
211    pub proof fn lemma_remove_key_len(self, key: K)
212        requires
213            self.dom().contains(key),
214        ensures
215            self.dom().len() == 1 + self.remove(key).dom().len(),
216    {
217    }
218
219    /// The domain of a map after removing a key is equivalent to removing the key from
220    /// the domain of the original map.
221    pub proof fn lemma_remove_equivalency(self, key: K)
222        ensures
223            self.remove(key).dom() == self.dom().remove(key),
224    {
225    }
226
227    /// Removing a set of n keys from a map that previously contained all n keys
228    /// results in a domain of size n less than the original domain.
229    pub proof fn lemma_remove_keys_len(self, keys: Set<K>)
230        requires
231            forall|k: K| #[trigger] keys.contains(k) ==> self.contains_key(k),
232        ensures
233            self.remove_keys(keys).dom().len() == self.dom().len() - keys.len(),
234        decreases keys.len(),
235    {
236        broadcast use group_set_properties;
237
238        if keys.len() > 0 {
239            let key = keys.choose();
240            let val = self[key];
241            self.remove(key).lemma_remove_keys_len(keys.remove(key));
242            assert(self.remove(key).remove_keys(keys.remove(key)) =~= self.remove_keys(keys));
243        } else {
244            assert(self.remove_keys(keys) =~= self);
245        }
246    }
247
248    /// The function `invert` results in an injective map
249    pub proof fn lemma_invert_is_injective(self)
250        ensures
251            self.invert().is_injective(),
252    {
253        assert forall|x: V, y: V|
254            x != y && self.invert().dom().contains(x) && self.invert().dom().contains(
255                y,
256            ) implies #[trigger] self.invert()[x] != #[trigger] self.invert()[y] by {
257            assert(exists|i: K| #[trigger] self.dom().contains(i) && self[i] == x);
258            let i = choose|i: K| #[trigger] self.dom().contains(i) && self[i] == x;
259            assert(self.contains_pair(i, x));
260            let j = choose|j: K| self.contains_pair(j, x) && self.invert()[x] == j;
261            assert(exists|k: K| #[trigger] self.dom().contains(k) && self[k] == y);
262            let k = choose|k: K| #[trigger] self.dom().contains(k) && self[k] == y;
263            assert(self.contains_pair(k, y));
264            let l = choose|l: K| self.contains_pair(l, y) && self.invert()[y] == l && l != j;
265        }
266    }
267
268    /// Keeps only those key-value pairs whose key satisfies `p`.
269    ///
270    /// ## Example
271    /// ```rust
272    /// proof fn example() {
273    ///     let m = map![1 => 10, 2 => 20];
274    ///     let even = |k: int| k % 2 == 0;
275    ///     assert(m.filter_keys(even) =~= map![2 => 20]);
276    /// }
277    /// ```
278    pub open spec fn filter_keys(self, p: spec_fn(K) -> bool) -> Self {
279        self.restrict(self.dom().filter(p))
280    }
281
282    /// Returns the value associated with key `k` in the map if it exists,
283    /// otherwise returns None.
284    ///
285    /// ## Example
286    /// ```rust
287    /// proof fn get_test() {
288    ///     let m: Map<int, bool> = map![
289    ///         1 => true,
290    ///         2 => false
291    ///     ];
292    ///
293    ///     assert(m.get(1) == Some(true));
294    ///     assert(m.get(3) == None);
295    /// }
296    /// ```
297    pub open spec fn get(self, k: K) -> Option<V> {
298        if self.dom().contains(k) {
299            Some(self[k])
300        } else {
301            None
302        }
303    }
304
305    /// A map contains a value satisfying predicate `p` iff some key maps to a value satisfying `p`.
306    ///
307    /// ## Example
308    /// ```rust
309    /// proof fn get_dom_value_any_test() {
310    ///     let m = map![1 => 10, 2 => 20, 3 => 30];
311    ///     let p = |v: int| v > 25;
312    ///     assert(m[3] == 30);
313    ///     assert(m.dom().any(|k| p(m[k])));
314    /// }
315    /// ```
316    pub proof fn get_dom_value_any(self, p: spec_fn(V) -> bool)
317        ensures
318            self.dom().any(|k: K| p(self[k])) <==> self.values().any(p),
319    {
320        broadcast use group_map_properties;
321
322        if self.dom().any(|k: K| p(self[k])) {
323            let k = choose|k: K| self.dom().contains(k) && #[trigger] p(self[k]);
324            assert(self.values().contains(self[k]));
325            assert(self.values().any(p));
326        }
327    }
328
329    /// Two maps are equal if and only if they are submaps of each other.
330    ///
331    /// ## Example
332    /// ```rust
333    /// proof fn submap_eq_test() {
334    ///     let m1 = map![1 => 10, 2 => 20];
335    ///     let m2 = map![1 => 10, 2 => 20];
336    ///     let m3 = map![1 => 10, 2 => 30];
337    ///
338    ///     assert(m1.submap_of(m2) && m2.submap_of(m1));
339    ///     assert(m1 == m2);
340    /// }
341    /// ```
342    pub proof fn lemma_submap_eq_iff(self, m: Self)
343        ensures
344            (self == m) <==> (self.submap_of(m) && m.submap_of(self)),
345    {
346        broadcast use group_map_properties;
347
348        if self.submap_of(m) && m.submap_of(self) {
349            assert(self.dom() == m.dom());
350            assert(self == m);
351        }
352    }
353
354    /// When removing a set of keys from a map after inserting (k,v),
355    /// the result depends on whether k is in the set:
356    /// if k is in the set, the insertion is discarded;
357    /// if not, the insertion happens after removal.
358    ///
359    /// ## Example
360    /// ```rust
361    /// proof fn map_remove_keys_insert_test() {
362    ///     let m = map![1 => 10, 2 => 20, 3 => 30];
363    ///     let to_remove = set![2, 4];
364    ///
365    ///     // 5 not in m: insert happens after remove
366    ///     assert(m.insert(5, 15).remove_keys(to_remove) == m.remove_keys(to_remove).insert(5, 15));
367    ///
368    ///     // 2 in m: insert is eliminated by remove
369    ///     assert(m.insert(2, 25).remove_keys(to_remove) == m.remove_keys(to_remove));
370    /// }
371    /// ```
372    pub broadcast proof fn lemma_map_remove_keys_insert(self, r: Set<K>, k: K, v: V)
373        ensures
374            #[trigger] self.insert(k, v).remove_keys(r) == if r.contains(k) {
375                self.remove_keys(r)
376            } else {
377                self.remove_keys(r).insert(k, v)
378            },
379    {
380        broadcast use group_map_properties;
381
382        let lhs = self.insert(k, v).remove_keys(r);
383        let rhs = if r.contains(k) {
384            self.remove_keys(r)
385        } else {
386            self.remove_keys(r).insert(k, v)
387        };
388        assert(lhs == rhs);
389    }
390
391    /// Filtering keys after inserting `(k, v)` leaves the result unchanged when `p(k)` is false,
392    /// and otherwise adds `(k, v)` to the already-filtered map.
393    ///
394    /// ## Example
395    /// ```rust
396    /// proof fn example() {
397    ///     let m = map![1 => 10];
398    ///     let even = |k: int| k % 2 == 0;
399    ///
400    ///     assert(m.insert(3, 30).filter_keys(even) =~= m.filter_keys(even));
401    ///     assert(m.insert(2, 20).filter_keys(even)
402    ///            =~= m.filter_keys(even).insert(2, 20));
403    /// }
404    /// ```
405    pub broadcast proof fn lemma_filter_keys_insert(self, p: spec_fn(K) -> bool, k: K, v: V)
406        ensures
407            #[trigger] self.insert(k, v).filter_keys(p) == (if p(k) {
408                self.filter_keys(p).insert(k, v)
409            } else {
410                self.filter_keys(p)
411            }),
412    {
413        broadcast use group_map_properties;
414
415        let lhs = self.insert(k, v).filter_keys(p);
416        let rhs = if p(k) {
417            self.filter_keys(p).insert(k, v)
418        } else {
419            self.filter_keys(p)
420        };
421        assert(lhs == rhs);
422    }
423
424    /// Inserting a value in a map means it contains the value that was inserted.
425    ///
426    /// ## Example
427    /// ```rust
428    /// proof fn example() {
429    ///     let a = map![1int => 2int];
430    ///     assert(a.contains_value(2));
431    /// }
432    /// ```
433    pub broadcast proof fn lemma_insert_contains_value(self, k: K, v: V)
434        ensures
435            #[trigger] self.insert(k, v).contains_value(v),
436    {
437        assert(self.insert(k, v).contains_key(k));
438    }
439
440    /// Inserting a value in a map where that key is already present ensures
441    /// The contains value sees (only) the updated value;
442    ///
443    /// ## Example
444    /// ```rust
445    /// proof fn example() {
446    ///     let a = map![1int => 2int].insert(1int, 3int);
447    ///     assert(!a.contains_value(2));
448    ///     assert(a.contains_value(3));
449    /// }
450    /// ```
451    pub broadcast proof fn lemma_insert_invariant_contains(self, old_v: V, k: K, v: V)
452        requires
453            self.contains_key(k) ==> self[k] != old_v,
454            old_v != v,
455        ensures
456            #[trigger] self.insert(k, v).contains_value(old_v) == self.contains_value(old_v),
457    {
458        if self.contains_value(old_v) {
459            let old_k = choose|key: K| #[trigger] self.dom().contains(key) && self[key] == old_v;
460            assert(self.insert(k, v).contains_key(old_k));
461        }
462    }
463
464    pub proof fn lemma_injective_values_len(self)
465        requires
466            self.is_injective(),
467        ensures
468            self.values().len() == self.dom().len(),
469    {
470        let f = |k: K|
471            if self.contains_key(k) {
472                self[k]
473            } else {
474                arbitrary()
475            };
476        assert(forall|a1: K, a2: K|
477            self.dom().contains(a1) && self.dom().contains(a2) && #[trigger] f(a1) == #[trigger] f(
478                a2,
479            ) ==> a1 == a2);
480        assert(self.dom().map(f) == self.values());
481        lemma_map_size(self.dom(), self.values(), f);
482    }
483
484    pub proof fn lemma_values_len(self)
485        ensures
486            self.values().len() <= self.dom().len(),
487    {
488        let f = |k: K|
489            if self.contains_key(k) {
490                self[k]
491            } else {
492                Set::<V>::full().unwrap().difference(self.values()).choose()
493            };
494        assert(self.dom().map(f) == self.values());
495        lemma_map_size_bound(self.dom(), self.values(), f);
496    }
497}
498
499impl<K, V> Map<Seq<K>, V> {
500    /// Returns a sub-map of all entries whose key begins with `prefix`,
501    /// re-indexed so that the stored keys have that prefix removed.
502    ///
503    /// ## Example
504    /// ```rust
505    /// proof fn example() {
506    ///     let m = map![seq![1, 2] => 10, seq![1, 2, 3] => 20, seq![2] => 30];
507    ///     let sub = m.prefixed_entries(seq![1, 2]);
508    ///
509    ///     assert(sub.contains_key(seq![]));          // original key [1,2]
510    ///     assert(sub[seq![]] == 10);
511    ///
512    ///     assert(sub.contains_key(seq![3]));         // original key [1,2,3]
513    ///     assert(sub[seq![3]] == 20);
514    ///
515    ///     assert(!sub.contains_key(seq![2]));        // original key [2] was not prefixed
516    /// }
517    /// ```
518    pub open spec fn prefixed_entries(self, prefix: Seq<K>) -> Self {
519        Map::new(
520            Set::new(|k: Seq<K>| self.contains_key(prefix + k)).unwrap(),
521            |k: Seq<K>| self[prefix + k],
522        )
523    }
524
525    /// This internal helper lemma says that if sequences `s1` and
526    /// `s2` differ, then they differ when prefixed by the sequence
527    /// `prefix`.
528    proof fn lemma_ne_implies_prefixed_ne(prefix: Seq<K>, s1: Seq<K>, s2: Seq<K>)
529        requires
530            s1 != s2,
531        ensures
532            prefix + s1 != prefix + s2,
533        decreases prefix.len(),
534    {
535        broadcast use super::seq::group_seq_axioms;
536
537        if s1.len() == s2.len() {
538            if forall|i: int| 0 <= i < s1.len() ==> s1[i] == s2[i] {
539                assert(s1 =~= s2);
540            } else {
541                let i: int = choose|i: int| 0 <= i < s1.len() && s1[i] != s2[i];
542                assert((prefix + s1)[prefix.len() + i] == s1[i]);
543                assert((prefix + s2)[prefix.len() + i] == s2[i]);
544            }
545        } else {
546            assert((prefix + s1).len() == prefix.len() + s1.len());
547            assert((prefix + s2).len() == prefix.len() + s2.len());
548        }
549    }
550
551    /// This helper lemma establishes that the set used in the body of
552    /// `prefixed_entries` is finite, so the set it produces is valid.
553    proof fn lemma_prefixed_entries_dom_finite(self, prefix: Seq<K>)
554        ensures
555            ISet::new(|k: Seq<K>| self.contains_key(prefix + k)).finite(),
556        decreases self.dom().len(),
557    {
558        let f = |k: Seq<K>| self.contains_key(prefix + k);
559        if forall|k: Seq<K>| !(#[trigger] self.contains_key(prefix + k)) {
560            assert(ISet::new(f) =~= ISet::empty());
561        } else {
562            let s: Seq<K> = choose|s: Seq<K>| #[trigger] self.contains_key(prefix + s);
563            self.remove(prefix + s).lemma_prefixed_entries_dom_finite(prefix);
564            let set_remove_f = |k: Seq<K>| self.remove(prefix + s).contains_key(prefix + k);
565            let is1 = ISet::new(f);
566            let is2 = ISet::new(set_remove_f).insert(s);
567            assert forall|x| is1.contains(x) implies is2.contains(x) by {
568                if x != s {
569                    Self::lemma_ne_implies_prefixed_ne(prefix, s, x);
570                    assert(self.remove(prefix + s).contains_key(prefix + x));
571                }
572            }
573            assert(ISet::new(f) =~= ISet::new(set_remove_f).insert(s));
574        }
575    }
576
577    /// For every key `k` kept by `prefixed_entries(prefix)`,
578    /// the associated value is the one stored at `prefix + k` in the original map.
579    ///
580    /// ## Example
581    /// ```rust
582    /// proof fn example() {
583    ///     let m = map![seq![1, 2] => 10, seq![1, 2, 3] => 20];
584    ///     let p = seq![1, 2];
585    ///
586    ///     // key inside the sub-map
587    ///     assert(m.prefixed_entries(p)[seq![]] == m[p + seq![]]);      // 10
588    ///     assert(m.prefixed_entries(p)[seq![3]] == m[p + seq![3]]);    // 20
589    /// }
590    /// ```
591    pub broadcast proof fn lemma_prefixed_entries_get(self, prefix: Seq<K>, k: Seq<K>)
592        requires
593            self.prefixed_entries(prefix).contains_key(k),
594        ensures
595            self.prefixed_entries(prefix)[k] == #[trigger] self[prefix + k],
596    {
597        broadcast use group_map_properties;
598
599        self.lemma_prefixed_entries_dom_finite(prefix);
600    }
601
602    /// A key `k` is in `prefixed_entries(prefix)` exactly when the original map
603    /// contains the key `prefix + k`.
604    ///
605    /// ## Example
606    /// ```rust
607    /// proof fn example() {
608    ///     let m = map![seq![1, 2] => 10, seq![1, 2, 3] => 20];
609    ///     let p = seq![1, 2];
610    ///
611    ///     assert(m.prefixed_entries(p).contains_key(seq![])
612    ///            <==> m.contains_key(p + seq![]));
613    ///
614    ///     assert(m.prefixed_entries(p).contains_key(seq![3])
615    ///            <==> m.contains_key(p + seq![3]));
616    ///
617    ///     assert(!m.prefixed_entries(p).contains_key(seq![2]));
618    /// }
619    /// ```
620    pub broadcast proof fn lemma_prefixed_entries_contains(self, prefix: Seq<K>, k: Seq<K>)
621        ensures
622            #[trigger] self.prefixed_entries(prefix).contains_key(k) <==> self.contains_key(
623                prefix + k,
624            ),
625    {
626        broadcast use group_map_properties;
627
628        let lhs = self.prefixed_entries(prefix);
629        let rhs = self;
630
631        self.lemma_prefixed_entries_dom_finite(prefix);
632    }
633
634    /// Inserting `(prefix + k, v)` before taking `prefixed_entries(prefix)`
635    /// has the same effect as inserting `(k, v)` into the prefixed map.
636    ///
637    /// ## Example
638    /// ```rust
639    /// proof fn example() {
640    ///     let m = map![seq![1, 2] => 10];
641    ///     let p = seq![1, 2];
642    ///
643    ///     let left  = m.insert(p + seq![3], 20).prefixed_entries(p);
644    ///     let right = m.prefixed_entries(p).insert(seq![3], 20);
645    ///
646    ///     assert(left == right);
647    /// }
648    /// ```
649    pub broadcast proof fn lemma_prefixed_entries_insert(self, prefix: Seq<K>, k: Seq<K>, v: V)
650        ensures
651            #[trigger] self.insert(prefix + k, v).prefixed_entries(prefix) == self.prefixed_entries(
652                prefix,
653            ).insert(k, v),
654    {
655        broadcast use group_map_properties;
656        broadcast use super::seq::group_seq_axioms;
657        broadcast use super::seq_lib::group_seq_properties, super::seq_lib::lemma_seq_skip_of_skip;
658        broadcast use Map::lemma_prefixed_entries_contains, Map::lemma_prefixed_entries_get;
659
660        let lhs = self.insert(prefix + k, v).prefixed_entries(prefix);
661        let rhs = self.prefixed_entries(prefix).insert(k, v);
662        assert(lhs =~= rhs) by {
663            assert(forall|key| key != k ==> prefix.is_prefix_of(#[trigger] (prefix + key)));
664        }
665    }
666
667    /// Taking the entries that share `prefix` commutes with `union_prefer_right`:
668    /// union the two maps first and then strip the prefix, or strip the prefix from
669    /// each map and then union them—the resulting maps are identical.
670    ///
671    /// ## Example
672    /// ```rust
673    /// proof fn example() {
674    ///     let a = map![seq![1, 2] => 10, seq![2, 3] => 20];
675    ///     let b = map![seq![1, 2] => 99, seq![2, 4] => 40];
676    ///     let p = seq![2];
677    ///
678    ///     assert(
679    ///         a.union_prefer_right(b).prefixed_entries(p)
680    ///         == a.prefixed_entries(p).union_prefer_right(b.prefixed_entries(p))
681    ///     );
682    /// }
683    /// ```
684    pub broadcast proof fn lemma_prefixed_entries_union(self, m: Self, prefix: Seq<K>)
685        ensures
686            #[trigger] self.union_prefer_right(m).prefixed_entries(prefix) == self.prefixed_entries(
687                prefix,
688            ).union_prefer_right(m.prefixed_entries(prefix)),
689    {
690        broadcast use group_map_properties;
691        broadcast use
692            Map::lemma_prefixed_entries_contains,
693            Map::lemma_prefixed_entries_get,
694            Map::lemma_prefixed_entries_insert,
695        ;
696
697        let lhs = self.union_prefer_right(m).prefixed_entries(prefix);
698        let rhs = self.prefixed_entries(prefix).union_prefer_right(m.prefixed_entries(prefix));
699        assert(lhs == rhs);
700    }
701}
702
703impl Map<int, int> {
704    /// Returns `true` if a map is monotonic -- that is, if the mapping between ordered sets
705    /// preserves the regular `<=` ordering on integers.
706    pub open spec fn is_monotonic(self) -> bool {
707        forall|x: int, y: int|
708            self.dom().contains(x) && self.dom().contains(y) && x <= y ==> #[trigger] self[x]
709                <= #[trigger] self[y]
710    }
711
712    /// Returns `true` if and only if a map is monotonic, only considering keys greater than
713    /// or equal to start
714    pub open spec fn is_monotonic_from(self, start: int) -> bool {
715        forall|x: int, y: int|
716            self.dom().contains(x) && self.dom().contains(y) && start <= x <= y
717                ==> #[trigger] self[x] <= #[trigger] self[y]
718    }
719}
720
721// Proven lemmas
722pub broadcast proof fn lemma_union_insert_left<K, V>(m1: Map<K, V>, m2: Map<K, V>, k: K, v: V)
723    requires
724        !m2.contains_key(k),
725    ensures
726        #[trigger] m1.insert(k, v).union_prefer_right(m2) == m1.union_prefer_right(m2).insert(k, v),
727{
728    assert(m1.insert(k, v).union_prefer_right(m2) =~= m1.union_prefer_right(m2).insert(k, v));
729}
730
731pub broadcast proof fn lemma_union_insert_right<K, V>(m1: Map<K, V>, m2: Map<K, V>, k: K, v: V)
732    ensures
733        #[trigger] m1.union_prefer_right(m2.insert(k, v)) == m1.union_prefer_right(m2).insert(k, v),
734{
735    assert(m1.union_prefer_right(m2.insert(k, v)) =~= m1.union_prefer_right(m2).insert(k, v));
736}
737
738pub broadcast proof fn lemma_union_remove_left<K, V>(m1: Map<K, V>, m2: Map<K, V>, k: K)
739    requires
740        m1.contains_key(k),
741        !m2.contains_key(k),
742    ensures
743        #[trigger] m1.union_prefer_right(m2).remove(k) == m1.remove(k).union_prefer_right(m2),
744{
745    assert(m1.remove(k).union_prefer_right(m2) =~= m1.union_prefer_right(m2).remove(k));
746}
747
748pub broadcast proof fn lemma_union_remove_right<K, V>(m1: Map<K, V>, m2: Map<K, V>, k: K)
749    requires
750        !m1.contains_key(k),
751        m2.contains_key(k),
752    ensures
753        #[trigger] m1.union_prefer_right(m2).remove(k) == m1.union_prefer_right(m2.remove(k)),
754{
755    assert(m1.union_prefer_right(m2.remove(k)) =~= m1.union_prefer_right(m2).remove(k));
756}
757
758pub broadcast proof fn lemma_union_dom<K, V>(m1: Map<K, V>, m2: Map<K, V>)
759    ensures
760        #[trigger] m1.union_prefer_right(m2).dom() == m1.dom().union(m2.dom()),
761{
762    assert(m1.dom().union(m2.dom()) =~= m1.union_prefer_right(m2).dom());
763}
764
765/// The size of the union of two disjoint maps is equal to the sum of the sizes of the individual maps
766pub broadcast proof fn lemma_disjoint_union_size<K, V>(m1: Map<K, V>, m2: Map<K, V>)
767    requires
768        m1.dom().disjoint(m2.dom()),
769    ensures
770        #[trigger] m1.union_prefer_right(m2).dom().len() == m1.dom().len() + m2.dom().len(),
771{
772    let u = m1.union_prefer_right(m2);
773    assert(u.dom() =~= m1.dom() + m2.dom());
774    assert(u.remove_keys(m1.dom()).dom() =~= m2.dom());
775    assert(u.remove_keys(m1.dom()).dom().len() == u.dom().len() - m1.dom().len()) by {
776        u.lemma_remove_keys_len(m1.dom());
777    }
778}
779
780pub broadcast group group_map_union {
781    lemma_union_dom,
782    lemma_union_remove_left,
783    lemma_union_remove_right,
784    lemma_union_insert_left,
785    lemma_union_insert_right,
786    lemma_disjoint_union_size,
787}
788
789/// submap_of (<=) is transitive.
790pub broadcast proof fn lemma_submap_of_trans<K, V>(m1: Map<K, V>, m2: Map<K, V>, m3: Map<K, V>)
791    requires
792        #[trigger] m1.submap_of(m2),
793        #[trigger] m2.submap_of(m3),
794    ensures
795        m1.submap_of(m3),
796{
797    assert forall|k| m1.dom().contains(k) implies #[trigger] m3.dom().contains(k) && m1[k]
798        == m3[k] by {
799        assert(m2.dom().contains(k));
800    }
801}
802
803// This verified lemma corresponds to an axiom in the Dafny prelude saying that:
804/// The domain of a map constructed with `Map::new(fk, fv)` is equivalent to the set constructed with `Set::new(fk)`.
805pub broadcast proof fn lemma_map_new_domain<K, V>(s: Set<K>, fv: spec_fn(K) -> V)
806    ensures
807        #[trigger] Map::<K, V>::new(s, fv).dom() == s,
808{
809}
810
811// This verified lemma used to be an axiom in the Dafny prelude saying that:
812/// The set of values of a map constructed with `Map::new(fk, fv)` is equivalent to
813/// the set constructed with `Set::new(|v: V| (exists |k: K| fk(k) && fv(k) == v)`. In other words,
814/// the set of all values fv(k) where fk(k) is true.
815pub broadcast proof fn lemma_map_new_values<K, V>(s: Set<K>, fv: spec_fn(K) -> V)
816    ensures
817        #[trigger] Map::<K, V>::new(s, fv).values() == s.map(fv),
818{
819}
820
821pub broadcast group group_map_properties {
822    lemma_map_new_domain,
823    lemma_map_new_values,
824}
825
826pub broadcast group group_map_extra {
827    Map::lemma_map_remove_keys_insert,
828    Map::lemma_filter_keys_insert,
829    Map::lemma_insert_contains_value,
830    Map::lemma_insert_invariant_contains,
831    Map::lemma_prefixed_entries_get,
832    Map::lemma_prefixed_entries_contains,
833    Map::lemma_prefixed_entries_insert,
834    Map::lemma_prefixed_entries_union,
835}
836
837} // verus!