1#![allow(unused_imports)]
2
3use super::pervasive::*;
4use super::prelude::*;
5use super::set::*;
6
7use verus as verus_; verus_! {
9
10#[verifier::ext_equal]
31#[verifier::reject_recursive_types(K)]
32#[verifier::accept_recursive_types(V)]
33pub tracked struct Map<K, V> {
34 mapping: spec_fn(K) -> Option<V>,
35}
36
37impl<K, V> Map<K, V> {
38 pub closed spec fn empty() -> Map<K, V> {
40 Map { mapping: |k| None }
41 }
42
43 pub open spec fn total(fv: spec_fn(K) -> V) -> Map<K, V> {
46 Set::full().mk_map(fv)
47 }
48
49 pub open spec fn new(fk: spec_fn(K) -> bool, fv: spec_fn(K) -> V) -> Map<K, V> {
52 Set::new(fk).mk_map(fv)
53 }
54
55 pub closed spec fn dom(self) -> Set<K> {
57 Set::new(|k| (self.mapping)(k) is Some)
58 }
59
60 pub closed spec fn index(self, key: K) -> V
63 recommends
64 self.dom().contains(key),
65 {
66 (self.mapping)(key)->Some_0
67 }
68
69 #[verifier::inline]
71 pub open spec fn spec_index(self, key: K) -> V
72 recommends
73 self.dom().contains(key),
74 {
75 self.index(key)
76 }
77
78 pub closed spec fn insert(self, key: K, value: V) -> Map<K, V> {
83 Map {
84 mapping: |k|
85 if k == key {
86 Some(value)
87 } else {
88 (self.mapping)(k)
89 },
90 }
91 }
92
93 pub closed spec fn remove(self, key: K) -> Map<K, V> {
97 Map {
98 mapping: |k|
99 if k == key {
100 None
101 } else {
102 (self.mapping)(k)
103 },
104 }
105 }
106
107 pub open spec fn len(self) -> nat {
109 self.dom().len()
110 }
111
112 pub axiom fn tracked_empty() -> (tracked out_v: Self)
116 ensures
117 out_v == Map::<K, V>::empty(),
118 ;
119
120 pub axiom fn tracked_insert(tracked &mut self, key: K, tracked value: V)
125 ensures
126 *final(self) == Map::insert(*old(self), key, value),
127 ;
128
129 pub axiom fn tracked_remove(tracked &mut self, key: K) -> (tracked v: V)
133 requires
134 old(self).dom().contains(key),
135 ensures
136 *final(self) == Map::remove(*old(self), key),
137 v == old(self)[key],
138 ;
139
140 pub axiom fn tracked_borrow(tracked &self, key: K) -> (tracked v: &V)
142 requires
143 self.dom().contains(key),
144 ensures
145 *v == self.index(key),
146 ;
147
148 pub axiom fn tracked_borrow_mut(tracked &mut self, key: K) -> (tracked v: &mut V)
150 requires
151 self.dom().contains(key),
152 ensures
153 *v == old(self).index(key),
154 *final(self) == old(self).insert(key, *final(v))
155 ;
156
157 pub axiom fn tracked_borrow_mut_split(tracked &mut self, keys: Set<K>)
159 -> (tracked (m1, m2): (&mut Self, &mut Self))
160 requires
161 keys <= self.dom(),
162 ensures
163 *m1 == old(self).restrict(keys),
164 *m2 == old(self).remove_keys(keys),
165 *final(self) == final(m1).union_prefer_right(*final(m2)),
166 ;
167
168 pub axiom fn tracked_map_keys<J>(
173 tracked old_map: Map<K, V>,
174 key_map: Map<J, K>,
175 ) -> (tracked new_map: Map<J, V>)
176 requires
177 forall|j| #![auto] key_map.contains_key(j) ==> old_map.contains_key(key_map[j]),
178 forall|j1, j2|
179 #![auto]
180 j1 != j2 && key_map.contains_key(j1) && key_map.contains_key(j2) ==> key_map[j1]
181 != key_map[j2],
182 ensures
183 new_map.dom() == key_map.dom(),
184 forall|j|
185 key_map.contains_key(j) ==> new_map.contains_key(j) && #[trigger] new_map[j]
186 == old_map[key_map[j]],
187 ;
188
189 pub axiom fn tracked_remove_keys(tracked &mut self, keys: Set<K>) -> (tracked out_map: Map<
193 K,
194 V,
195 >)
196 requires
197 keys.subset_of(old(self).dom()),
198 ensures
199 *final(self) == old(self).remove_keys(keys),
200 out_map == old(self).restrict(keys),
201 ;
202
203 pub axiom fn tracked_union_prefer_right(tracked &mut self, right: Self)
207 ensures
208 *final(self) == old(self).union_prefer_right(right),
209 ;
210}
211
212pub broadcast axiom fn axiom_map_index_decreases_finite<K, V>(m: Map<K, V>, key: K)
222 requires
223 m.dom().finite(),
224 m.dom().contains(key),
225 ensures
226 #[trigger] (decreases_to!(m => m[key])),
227;
228
229pub broadcast axiom fn axiom_map_index_decreases_infinite<K, V>(m: Map<K, V>, key: K)
232 requires
233 m.dom().contains(key),
234 ensures
235 #[trigger] is_smaller_than_recursive_function_field(m[key], m),
236;
237
238pub broadcast proof fn axiom_map_empty<K, V>()
240 ensures
241 #[trigger] Map::<K, V>::empty().dom() == Set::<K>::empty(),
242{
243 broadcast use super::set::group_set_axioms;
244
245 assert(Set::new(|k: K| (|k| None::<V>)(k) is Some) == Set::<K>::empty());
246}
247
248pub broadcast proof fn axiom_map_insert_domain<K, V>(m: Map<K, V>, key: K, value: V)
251 ensures
252 #[trigger] m.insert(key, value).dom() == m.dom().insert(key),
253{
254 broadcast use super::set::group_set_axioms;
255
256 assert(m.insert(key, value).dom() =~= m.dom().insert(key));
257}
258
259pub broadcast proof fn axiom_map_insert_same<K, V>(m: Map<K, V>, key: K, value: V)
261 ensures
262 #[trigger] m.insert(key, value)[key] == value,
263{
264}
265
266pub broadcast proof fn axiom_map_insert_different<K, V>(m: Map<K, V>, key1: K, key2: K, value: V)
268 requires
269 key1 != key2,
270 ensures
271 #[trigger] m.insert(key2, value)[key1] == m[key1],
272{
273}
274
275pub broadcast proof fn axiom_map_remove_domain<K, V>(m: Map<K, V>, key: K)
278 ensures
279 #[trigger] m.remove(key).dom() == m.dom().remove(key),
280{
281 broadcast use super::set::group_set_axioms;
282
283 assert(m.remove(key).dom() =~= m.dom().remove(key));
284}
285
286pub broadcast proof fn axiom_map_remove_different<K, V>(m: Map<K, V>, key1: K, key2: K)
289 requires
290 key1 != key2,
291 ensures
292 #[trigger] m.remove(key2)[key1] == m[key1],
293{
294}
295
296pub broadcast proof fn axiom_map_ext_equal<K, V>(m1: Map<K, V>, m2: Map<K, V>)
298 ensures
299 #[trigger] (m1 =~= m2) <==> {
300 &&& m1.dom() =~= m2.dom()
301 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]
302 },
303{
304 broadcast use super::set::group_set_axioms;
305
306 if m1 =~= m2 {
307 assert(m1.dom() =~= m2.dom());
308 assert(forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]);
309 }
310 if ({
311 &&& m1.dom() =~= m2.dom()
312 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]
313 }) {
314 if m1.mapping != m2.mapping {
315 assert(exists|k| #[trigger] (m1.mapping)(k) != (m2.mapping)(k));
316 let k = choose|k| #[trigger] (m1.mapping)(k) != (m2.mapping)(k);
317 if m1.dom().contains(k) {
318 assert(m1[k] == m2[k]);
319 }
320 assert(false);
321 }
322 assert(m1 =~= m2);
323 }
324}
325
326pub broadcast proof fn axiom_map_ext_equal_deep<K, V>(m1: Map<K, V>, m2: Map<K, V>)
327 ensures
328 #[trigger] (m1 =~~= m2) <==> {
329 &&& m1.dom() =~~= m2.dom()
330 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] =~~= m2[k]
331 },
332{
333 axiom_map_ext_equal(m1, m2);
334}
335
336pub broadcast group group_map_axioms {
337 axiom_map_index_decreases_finite,
338 axiom_map_index_decreases_infinite,
339 axiom_map_empty,
340 axiom_map_insert_domain,
341 axiom_map_insert_same,
342 axiom_map_insert_different,
343 axiom_map_remove_domain,
344 axiom_map_remove_different,
345 axiom_map_ext_equal,
346 axiom_map_ext_equal_deep,
347}
348
349#[doc(hidden)]
351#[macro_export]
352macro_rules! map_internal {
353 [$($key:expr => $value:expr),* $(,)?] => {
354 $crate::vstd::map::Map::empty()
355 $(.insert($key, $value))*
356 }
357}
358
359#[macro_export]
366macro_rules! map {
367 [$($tail:tt)*] => {
368 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::map::map_internal!($($tail)*))
369 };
370}
371
372#[doc(hidden)]
373#[verifier::inline]
374pub open spec fn check_argument_is_map<K, V>(m: Map<K, V>) -> Map<K, V> {
375 m
376}
377
378#[doc(hidden)]
379pub use map_internal;
380pub use map;
381
382#[macro_export]
428macro_rules! assert_maps_equal {
429 [$($tail:tt)*] => {
430 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::map::assert_maps_equal_internal!($($tail)*))
431 };
432}
433
434#[macro_export]
435#[doc(hidden)]
436macro_rules! assert_maps_equal_internal {
437 (::verus_builtin::spec_eq($m1:expr, $m2:expr)) => {
438 assert_maps_equal_internal!($m1, $m2)
439 };
440 (::verus_builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
441 assert_maps_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
442 };
443 ($m1:expr, $m2:expr $(,)?) => {
444 assert_maps_equal_internal!($m1, $m2, key => { })
445 };
446 ($m1:expr, $m2:expr, $k:ident $( : $t:ty )? => $bblock:block) => {
447 #[verifier::spec] let m1 = $crate::vstd::map::check_argument_is_map($m1);
448 #[verifier::spec] let m2 = $crate::vstd::map::check_argument_is_map($m2);
449 $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(m1, m2), {
450 $crate::vstd::prelude::assert_forall_by(|$k $( : $t )?| {
451 $crate::vstd::prelude::ensures([
454 $crate::vstd::prelude::imply(#[verifier::trigger] m1.dom().contains($k), m2.dom().contains($k))
455 && $crate::vstd::prelude::imply(m2.dom().contains($k), m1.dom().contains($k))
456 && $crate::vstd::prelude::imply(m1.dom().contains($k) && m2.dom().contains($k),
457 $crate::vstd::prelude::equal(m1.index($k), m2.index($k)))
458 ]);
459 { $bblock }
460 });
461 $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(m1, m2));
462 });
463 }
464}
465
466#[doc(hidden)]
467pub use assert_maps_equal_internal;
468pub use assert_maps_equal;
469
470} verus_! { impl<K, V> Map<K, V> {
475 pub proof fn tracked_map_keys_in_place(tracked &mut self, key_map: Map<K, K>)
476 requires
477 forall|j|
478 #![auto]
479 key_map.dom().contains(j) ==> old(self).dom().contains(key_map.index(j)),
480 forall|j1, j2|
481 #![auto]
482 j1 != j2 && key_map.dom().contains(j1) && key_map.dom().contains(j2)
483 ==> key_map.index(j1) != key_map.index(j2),
484 ensures
485 forall|j| #[trigger] final(self).dom().contains(j) == key_map.dom().contains(j),
486 forall|j|
487 key_map.dom().contains(j) ==> final(self).dom().contains(j) && #[trigger] final(self).index(j)
488 == old(self).index(key_map.index(j)),
489 {
490 let tracked mut tmp = Self::tracked_empty();
491 super::modes::tracked_swap(&mut tmp, self);
492 let tracked mut tmp = Self::tracked_map_keys(tmp, key_map);
493 super::modes::tracked_swap(&mut tmp, self);
494 }
495}
496
497}