1#![allow(unused_imports)]
2
3use super::pervasive::*;
4use super::prelude::*;
5use super::set::*;
6
7use verus as verus_; verus_! {
9
10broadcast use {
11 super::set::group_set_lemmas,
12 super::set_lib::group_set_lib_default,
13};
14
15#[verifier::ext_equal]
39#[verifier::external_body]
40#[verifier::accept_recursive_types(K)]
41#[verifier::accept_recursive_types(V)]
42pub tracked struct Map<K, V> {
43 dummy_key: core::marker::PhantomData<K>,
51 dummy_value: core::marker::PhantomData<V>,
52}
53
54impl<K, V> Map<K, V> {
55 pub uninterp spec fn dom(self) -> Set<K>;
57
58 pub uninterp spec fn index(self, key: K) -> V
61 recommends
62 self.dom().contains(key),
63 ;
64
65 pub uninterp spec fn new(s: Set<K>, fv: spec_fn(K) -> V) -> Map<K, V>;
68
69 broadcast axiom fn axiom_new(s: Set<K>, fv: spec_fn(K) -> V)
72 ensures
73 #![trigger Self::new(s, fv)]
74 Self::new(s, fv).dom() == s,
75 forall|k| s.contains(k) ==> #[trigger] Self::new(s, fv)[k] == fv(k),
76 ;
77
78 pub closed spec fn empty() -> Map<K, V> {
80 Self::new(Set::<K>::empty(), |k| arbitrary())
81 }
82
83 #[verifier::inline]
85 pub open spec fn spec_index(self, key: K) -> V
86 recommends
87 self.dom().contains(key),
88 {
89 self.index(key)
90 }
91
92 pub closed spec fn insert(self, key: K, value: V) -> Map<K, V> {
97 Map::new(self.dom().insert(key), |k| if k == key { value } else { self[k] })
98 }
99
100 pub closed spec fn remove(self, key: K) -> Map<K, V> {
104 Map::new(self.dom().remove(key), |k| self[k])
105 }
106
107 pub open spec fn len(self) -> nat {
109 self.dom().len()
110 }
111
112 pub open spec fn to_imap(self) -> IMap<K, V> {
114 IMap::new(|k| self.dom().contains(k), |k| self[k])
115 }
116
117 pub open spec fn congruent(self, m2: IMap<K, V>) -> bool {
119 &&& self.dom().congruent(m2.dom())
120 &&& forall|k| #[trigger] self.dom().contains(k) ==> self[k] == m2[k]
121 }
122
123 pub axiom fn tracked_empty() -> (tracked out_v: Self)
127 ensures
128 out_v == Map::<K, V>::empty(),
129 ;
130
131 pub axiom fn tracked_insert(tracked &mut self, key: K, tracked value: V)
136 ensures
137 *final(self) == Map::insert(*old(self), key, value),
138 ;
139
140 pub axiom fn tracked_remove(tracked &mut self, key: K) -> (tracked v: V)
144 requires
145 old(self).dom().contains(key),
146 ensures
147 *final(self) == Map::remove(*old(self), key),
148 v == old(self)[key],
149 ;
150
151 pub axiom fn tracked_borrow(tracked &self, key: K) -> (tracked v: &V)
153 requires
154 self.dom().contains(key),
155 ensures
156 *v == self.index(key),
157 ;
158
159 pub axiom fn tracked_borrow_mut(tracked &mut self, key: K) -> (tracked v: &mut V)
161 requires
162 self.dom().contains(key),
163 ensures
164 *v == old(self).index(key),
165 *final(self) == old(self).insert(key, *final(v))
166 ;
167
168 pub axiom fn tracked_borrow_mut_split(tracked &mut self, keys: Set<K>)
170 -> (tracked (m1, m2): (&mut Self, &mut Self))
171 requires
172 keys <= self.dom(),
173 ensures
174 *m1 == old(self).restrict(keys),
175 *m2 == old(self).remove_keys(keys),
176 *final(self) == final(m1).union_prefer_right(*final(m2)),
177 ;
178
179 pub axiom fn tracked_map_keys<J>(
184 tracked old_map: Map<K, V>,
185 key_map: Map<J, K>,
186 ) -> (tracked new_map: Map<J, V>)
187 requires
188 forall|j| #![auto] key_map.contains_key(j) ==> old_map.contains_key(key_map[j]),
189 forall|j1, j2|
190 #![auto]
191 j1 != j2 && key_map.contains_key(j1) && key_map.contains_key(j2) ==> key_map[j1]
192 != key_map[j2],
193 ensures
194 new_map.dom() == key_map.dom(),
195 forall|j|
196 key_map.contains_key(j) ==> new_map.contains_key(j) && #[trigger] new_map[j]
197 == old_map[key_map[j]],
198 ;
199
200 pub axiom fn tracked_remove_keys(tracked &mut self, keys: Set<K>) -> (tracked out_map: Map<
204 K,
205 V,
206 >)
207 requires
208 keys.subset_of(old(self).dom()),
209 ensures
210 *final(self) == old(self).remove_keys(keys),
211 out_map == old(self).restrict(keys),
212 ;
213
214 pub axiom fn tracked_union_prefer_right(tracked &mut self, right: Self)
218 ensures
219 *final(self) == old(self).union_prefer_right(right),
220 ;
221}
222
223pub broadcast axiom fn axiom_map_index_decreases<K, V>(m: Map<K, V>, key: K)
225 requires
226 m.dom().contains(key),
227 ensures
228 #[trigger](decreases_to!(m => m[key]));
229
230pub broadcast proof fn lemma_map_new_domain<K, V>(s: Set<K>, fv: spec_fn(K) -> V)
233 ensures
234 #![trigger Map::new(s, fv)]
235 Map::new(s, fv).dom() == s,
236{
237 broadcast use Map::axiom_new;
238}
239
240pub broadcast proof fn lemma_map_new_index<K, V>(s: Set<K>, fv: spec_fn(K) -> V, k: K)
243 requires
244 s.contains(k),
245 ensures
246 #![trigger Map::new(s, fv)[k]]
247 Map::new(s, fv)[k] == fv(k)
248{
249 broadcast use Map::axiom_new;
250}
251
252pub broadcast proof fn lemma_map_empty<K, V>()
254 ensures
255 #[trigger] Map::<K, V>::empty().dom() == Set::<K>::empty(),
256{
257 broadcast use Map::axiom_new;
258}
259
260pub broadcast proof fn lemma_map_insert_domain<K, V>(m: Map<K, V>, key: K, value: V)
263 ensures
264 #[trigger] m.insert(key, value).dom() == m.dom().insert(key),
265{
266 broadcast use Map::axiom_new;
267}
268
269pub broadcast proof fn lemma_map_insert_same<K, V>(m: Map<K, V>, key: K, value: V)
271 ensures
272 #[trigger] m.insert(key, value)[key] == value,
273{
274 broadcast use Map::axiom_new;
275}
276
277pub broadcast axiom fn axiom_map_insert_different<K, V>(m: Map<K, V>, key1: K, key2: K, value: V)
281 requires
282 key1 != key2,
283 ensures
284 #[trigger] m.insert(key2, value)[key1] == m[key1],
285;
286
287pub broadcast proof fn lemma_map_remove_domain<K, V>(m: Map<K, V>, key: K)
290 ensures
291 #[trigger] m.remove(key).dom() == m.dom().remove(key),
292{
293 broadcast use Map::axiom_new;
294}
295
296pub broadcast axiom fn axiom_map_remove_different<K, V>(m: Map<K, V>, key1: K, key2: K)
301 requires
302 key1 != key2,
303 ensures
304 #[trigger] m.remove(key2)[key1] == m[key1],
305;
306
307pub broadcast axiom fn axiom_map_ext_equal<K, V>(m1: Map<K, V>, m2: Map<K, V>)
309 ensures
310 #[trigger] (m1 =~= m2) <==> {
311 &&& m1.dom() =~= m2.dom()
312 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] == m2[k]
313 },
314;
315
316pub broadcast proof fn axiom_map_ext_equal_deep<K, V>(m1: Map<K, V>, m2: Map<K, V>)
320 ensures
321 #[trigger] (m1 =~~= m2) <==> {
322 &&& m1.dom() =~~= m2.dom()
323 &&& forall|k: K| #![auto] m1.dom().contains(k) ==> m1[k] =~~= m2[k]
324 },
325{
326 axiom_map_ext_equal(m1, m2);
327}
328
329pub broadcast group group_map_lemmas {
330 axiom_map_index_decreases,
331 lemma_map_new_domain,
332 lemma_map_new_index,
333 lemma_map_empty,
334 lemma_map_insert_domain,
335 lemma_map_insert_same,
336 axiom_map_insert_different,
337 lemma_map_remove_domain,
338 axiom_map_remove_different,
339 axiom_map_ext_equal,
340 axiom_map_ext_equal_deep,
341}
342
343#[doc(hidden)]
345#[macro_export]
346macro_rules! map_internal {
347 [$($key:expr => $value:expr),* $(,)?] => {
348 $crate::vstd::map::Map::empty()
349 $(.insert($key, $value))*
350 }
351}
352
353#[macro_export]
360macro_rules! map {
361 [$($tail:tt)*] => {
362 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::map::map_internal!($($tail)*))
363 };
364}
365
366#[doc(hidden)]
367#[verifier::inline]
368pub open spec fn check_argument_is_map<K, V>(m: Map<K, V>) -> Map<K, V> {
369 m
370}
371
372#[doc(hidden)]
373pub use map_internal;
374pub use map;
375
376#[macro_export]
422macro_rules! assert_maps_equal {
423 [$($tail:tt)*] => {
424 $crate::vstd::prelude::verus_proof_macro_exprs!($crate::vstd::map::assert_maps_equal_internal!($($tail)*))
425 };
426}
427
428#[macro_export]
429#[doc(hidden)]
430macro_rules! assert_maps_equal_internal {
431 (::verus_builtin::spec_eq($m1:expr, $m2:expr)) => {
432 assert_maps_equal_internal!($m1, $m2)
433 };
434 (::verus_builtin::spec_eq($m1:expr, $m2:expr), $k:ident $( : $t:ty )? => $bblock:block) => {
435 assert_maps_equal_internal!($m1, $m2, $k $( : $t )? => $bblock)
436 };
437 ($m1:expr, $m2:expr $(,)?) => {
438 assert_maps_equal_internal!($m1, $m2, key => { })
439 };
440 ($m1:expr, $m2:expr, $k:ident $( : $t:ty )? => $bblock:block) => {
441 #[verifier::spec] let m1 = $crate::vstd::map::check_argument_is_map($m1);
442 #[verifier::spec] let m2 = $crate::vstd::map::check_argument_is_map($m2);
443 $crate::vstd::prelude::assert_by($crate::vstd::prelude::equal(m1, m2), {
444 $crate::vstd::prelude::assert_forall_by(|$k $( : $t )?| {
445 $crate::vstd::prelude::ensures([
448 $crate::vstd::prelude::imply(#[verifier::trigger] m1.dom().contains($k), m2.dom().contains($k))
449 && $crate::vstd::prelude::imply(m2.dom().contains($k), m1.dom().contains($k))
450 && $crate::vstd::prelude::imply(m1.dom().contains($k) && m2.dom().contains($k),
451 $crate::vstd::prelude::equal(m1.index($k), m2.index($k)))
452 ]);
453 { $bblock }
454 });
455 $crate::vstd::prelude::assert_($crate::vstd::prelude::ext_equal(m1, m2));
456 });
457 }
458}
459
460#[doc(hidden)]
461pub use assert_maps_equal_internal;
462pub use assert_maps_equal;
463
464} verus_! { impl<K, V> Map<K, V> {
469 pub proof fn tracked_map_keys_in_place(tracked &mut self, key_map: Map<K, K>)
470 requires
471 forall|j|
472 #![auto]
473 key_map.dom().contains(j) ==> old(self).dom().contains(key_map.index(j)),
474 forall|j1, j2|
475 #![auto]
476 j1 != j2 && key_map.dom().contains(j1) && key_map.dom().contains(j2)
477 ==> key_map.index(j1) != key_map.index(j2),
478 ensures
479 forall|j| #[trigger] final(self).dom().contains(j) == key_map.dom().contains(j),
480 forall|j|
481 key_map.dom().contains(j) ==> final(self).dom().contains(j) && #[trigger] final(self).index(j)
482 == old(self).index(key_map.index(j)),
483 {
484 let tracked mut tmp = Self::tracked_empty();
485 super::modes::tracked_swap(&mut tmp, self);
486 let tracked mut tmp = Self::tracked_map_keys(tmp, key_map);
487 super::modes::tracked_swap(&mut tmp, self);
488 }
489}
490
491}