1#![allow(unused_imports)]
2
3use super::pervasive::*;
4use super::prelude::*;
5use super::set::*;
6
7verus! {
8
9#[verifier::ext_equal]
30#[verifier::reject_recursive_types(K)]
31#[verifier::accept_recursive_types(V)]
32pub tracked struct Map<K, V> {
33 mapping: spec_fn(K) -> Option<V>,
34}
35
36impl<K, V> Map<K, V> {
37 pub closed spec fn empty() -> Map<K, V> {
39 Map { mapping: |k| None }
40 }
41
42 pub open spec fn total(fv: spec_fn(K) -> V) -> Map<K, V> {
45 Set::full().mk_map(fv)
46 }
47
48 pub open spec fn new(fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V) -> Map<K, V> {
51 Set::new(fk).mk_map(fv)
52 }
53
54 pub closed spec fn dom(self) -> Set<K> {
56 Set::new(|k| (self.mapping)(k) is Some)
57 }
58
59 pub closed spec fn index(self, key: K) -> V
62 recommends
63 self.dom().contains(key),
64 {
65 (self.mapping)(key)->Some_0
66 }
67
68 #[verifier::inline]
70 pub open spec fn spec_index(self, key: K) -> V
71 recommends
72 self.dom().contains(key),
73 {
74 self.index(key)
75 }
76
77 pub closed spec fn insert(self, key: K, value: V) -> Map<K, V> {
82 Map {
83 mapping: |k|
84 if k == key {
85 Some(value)
86 } else {
87 (self.mapping)(k)
88 },
89 }
90 }
91
92 pub closed spec fn remove(self, key: K) -> Map<K, V> {
96 Map {
97 mapping: |k|
98 if k == key {
99 None
100 } else {
101 (self.mapping)(k)
102 },
103 }
104 }
105
106 pub open spec fn len(self) -> nat {
108 self.dom().len()
109 }
110
111 pub axiom fn tracked_empty() -> (tracked out_v: Self)
115 ensures
116 out_v == Map::<K, V>::empty(),
117 ;
118
119 pub axiom fn tracked_insert(tracked &mut self, key: K, tracked value: V)
124 ensures
125 *self == Map::insert(*old(self), key, value),
126 ;
127
128 pub axiom fn tracked_remove(tracked &mut self, key: K) -> (tracked v: V)
132 requires
133 old(self).dom().contains(key),
134 ensures
135 *self == Map::remove(*old(self), key),
136 v == old(self)[key],
137 ;
138
139 pub axiom fn tracked_borrow(tracked &self, key: K) -> (tracked v: &V)
141 requires
142 self.dom().contains(key),
143 ensures
144 *v === self.index(key),
145 ;
146
147 pub axiom fn tracked_map_keys<J>(
152 tracked old_map: Map<K, V>,
153 key_map: Map<J, K>,
154 ) -> (tracked new_map: Map<J, V>)
155 requires
156 forall|j| #![auto] key_map.contains_key(j) ==> old_map.contains_key(key_map[j]),
157 forall|j1, j2|
158 #![auto]
159 j1 != j2 && key_map.contains_key(j1) && key_map.contains_key(j2) ==> key_map[j1]
160 != key_map[j2],
161 ensures
162 new_map.dom() == key_map.dom(),
163 forall|j|
164 key_map.contains_key(j) ==> new_map.contains_key(j) && #[trigger] new_map[j]
165 == old_map[key_map[j]],
166 ;
167
168 pub axiom fn tracked_remove_keys(tracked &mut self, keys: Set<K>) -> (tracked out_map: Map<
172 K,
173 V,
174 >)
175 requires
176 keys.subset_of(old(self).dom()),
177 ensures
178 *self == old(self).remove_keys(keys),
179 out_map == old(self).restrict(keys),
180 ;
181
182 pub axiom fn tracked_union_prefer_right(tracked &mut self, right: Self)
186 ensures
187 *self == old(self).union_prefer_right(right),
188 ;
189}
190
191pub broadcast axiom fn axiom_map_index_decreases_finite<K, V>(m: Map<K, V>, key: K)
201 requires
202 m.dom().finite(),
203 m.dom().contains(key),
204 ensures
205 #[trigger] (decreases_to!(m => m[key])),
206;
207
208pub broadcast axiom fn axiom_map_index_decreases_infinite<K, V>(m: Map<K, V>, key: K)
211 requires
212 m.dom().contains(key),
213 ensures
214 #[trigger] is_smaller_than_recursive_function_field(m[key], m),
215;
216
217pub broadcast proof fn axiom_map_empty<K, V>()
219 ensures
220 #[trigger] Map::<K, V>::empty().dom() == Set::<K>::empty(),
221{
222 broadcast use super::set::group_set_axioms;
223
224 assert(Set::new(|k: K| (|k| None::<V>)(k) is Some) == Set::<K>::empty());
225}
226
227pub broadcast proof fn axiom_map_insert_domain<K, V>(m: Map<K, V>, key: K, value: V)
230 ensures
231 #[trigger] m.insert(key, value).dom() == m.dom().insert(key),
232{
233 broadcast use super::set::group_set_axioms;
234
235 assert(m.insert(key, value).dom() =~= m.dom().insert(key));
236}
237
238pub broadcast proof fn axiom_map_insert_same<K, V>(m: Map<K, V>, key: K, value: V)
240 ensures
241 #[trigger] m.insert(key, value)[key] == value,
242{
243}
244
245pub broadcast proof fn axiom_map_insert_different<K, V>(m: Map<K, V>, key1: K, key2: K, value: V)
247 requires
248 key1 != key2,
249 ensures
250 #[trigger] m.insert(key2, value)[key1] == m[key1],
251{
252}
253
254pub broadcast proof fn axiom_map_remove_domain<K, V>(m: Map<K, V>, key: K)
257 ensures
258 #[trigger] m.remove(key).dom() == m.dom().remove(key),
259{
260 broadcast use super::set::group_set_axioms;
261
262 assert(m.remove(key).dom() =~= m.dom().remove(key));
263}
264
265pub broadcast proof fn axiom_map_remove_different<K, V>(m: Map<K, V>, key1: K, key2: K)
268 requires
269 key1 != key2,
270 ensures
271 #[trigger] m.remove(key2)[key1] == m[key1],
272{
273}
274
275pub broadcast proof fn axiom_map_ext_equal<K, V>(m1: Map<K, V>, m2: Map<K, V>)
277 ensures
278 #[trigger] (m1 =~= m2) <==> {
279 &&& m1.dom() =~= m2.dom()
280 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]
281 },
282{
283 broadcast use super::set::group_set_axioms;
284
285 if m1 =~= m2 {
286 assert(m1.dom() =~= m2.dom());
287 assert(forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]);
288 }
289 if ({
290 &&& m1.dom() =~= m2.dom()
291 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]
292 }) {
293 if m1.mapping != m2.mapping {
294 assert(exists|k| #[trigger] (m1.mapping)(k) != (m2.mapping)(k));
295 let k = choose|k| #[trigger] (m1.mapping)(k) != (m2.mapping)(k);
296 if m1.dom().contains(k) {
297 assert(m1[k] == m2[k]);
298 }
299 assert(false);
300 }
301 assert(m1 =~= m2);
302 }
303}
304
305pub broadcast proof fn axiom_map_ext_equal_deep<K, V>(m1: Map<K, V>, m2: Map<K, V>)
306 ensures
307 #[trigger] (m1 =~~= m2) <==> {
308 &&& m1.dom() =~~= m2.dom()
309 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] =~~= m2[k]
310 },
311{
312 axiom_map_ext_equal(m1, m2);
313}
314
315pub broadcast group group_map_axioms {
316 axiom_map_index_decreases_finite,
317 axiom_map_index_decreases_infinite,
318 axiom_map_empty,
319 axiom_map_insert_domain,
320 axiom_map_insert_same,
321 axiom_map_insert_different,
322 axiom_map_remove_domain,
323 axiom_map_remove_different,
324 axiom_map_ext_equal,
325 axiom_map_ext_equal_deep,
326}
327
328#[doc(hidden)]
330#[macro_export]
331macro_rules! map_internal {
332 [$($key:expr => $value:expr),* $(,)?] => {
333 $crate::vstd::map::Map::empty()
334 $(.insert($key, $value))*
335 }
336}
337
338#[macro_export]
345macro_rules! map {
346 [$($tail:tt)*] => {
347 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::map::map_internal!($($tail)*))
348 };
349}
350
351#[doc(hidden)]
352#[verifier::inline]
353pub open spec fn check_argument_is_map<K, V>(m: Map<K, V>) -> Map<K, V> {
354 m
355}
356
357#[doc(hidden)]
358pub use map_internal;
359pub use map;
360
361#[macro_export]
407macro_rules! assert_maps_equal {
408 [$($tail:tt)*] => {
409 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::map::assert_maps_equal_internal!($($tail)*))
410 };
411}
412
413#[macro_export]
414#[doc(hidden)]
415macro_rules! assert_maps_equal_internal {
416 (::verus_builtin::spec_eq($m1:expr, $m2:expr)) => {
417 assert_maps_equal_internal!($m1, $m2)
418 };
419 (::verus_builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
420 assert_maps_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
421 };
422 ($m1:expr, $m2:expr $(,)?) => {
423 assert_maps_equal_internal!($m1, $m2, key => { })
424 };
425 ($m1:expr, $m2:expr, $k:ident $( : $t:ty )? => $bblock:block) => {
426 #[verifier::spec] let m1 = $crate::vstd::map::check_argument_is_map($m1);
427 #[verifier::spec] let m2 = $crate::vstd::map::check_argument_is_map($m2);
428 $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(m1, m2), {
429 $crate::vstd::prelude::assert_forall_by(|$k $( : $t )?| {
430 $crate::vstd::prelude::ensures([
433 $crate::vstd::prelude::imply(#[verifier::trigger] m1.dom().contains($k), m2.dom().contains($k))
434 && $crate::vstd::prelude::imply(m2.dom().contains($k), m1.dom().contains($k))
435 && $crate::vstd::prelude::imply(m1.dom().contains($k) && m2.dom().contains($k),
436 $crate::vstd::prelude::equal(m1.index($k), m2.index($k)))
437 ]);
438 { $bblock }
439 });
440 $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(m1, m2));
441 });
442 }
443}
444
445#[doc(hidden)]
446pub use assert_maps_equal_internal;
447pub use assert_maps_equal;
448
449impl<K, V> Map<K, V> {
450 pub proof fn tracked_map_keys_in_place(tracked &mut self, key_map: Map<K, K>)
451 requires
452 forall|j|
453 #![auto]
454 key_map.dom().contains(j) ==> old(self).dom().contains(key_map.index(j)),
455 forall|j1, j2|
456 #![auto]
457 j1 != j2 && key_map.dom().contains(j1) && key_map.dom().contains(j2)
458 ==> key_map.index(j1) != key_map.index(j2),
459 ensures
460 forall|j| #[trigger] self.dom().contains(j) == key_map.dom().contains(j),
461 forall|j|
462 key_map.dom().contains(j) ==> self.dom().contains(j) && #[trigger] self.index(j)
463 == old(self).index(key_map.index(j)),
464 {
465 let tracked mut tmp = Self::tracked_empty();
466 super::modes::tracked_swap(&mut tmp, self);
467 let tracked mut tmp = Self::tracked_map_keys(tmp, key_map);
468 super::modes::tracked_swap(&mut tmp, self);
469 }
470}
471
472}