1use super::super::laws_eq::{obeys_concrete_eq, obeys_deep_eq};
39use super::super::map::{assert_maps_equal, assert_maps_equal_internal};
40use super::super::prelude::*;
41use super::borrow::BorrowSpec;
42use super::cmp::PartialEqSpec;
43use super::iter::IteratorSpec;
44
45use core::alloc::Allocator;
46use core::borrow::Borrow;
47use core::hash::{BuildHasher, Hash, Hasher};
48use core::marker::PhantomData;
49use core::option::Option;
50use core::option::Option::None;
51use std::collections::hash_map;
52use std::collections::hash_map::{
53 DefaultHasher, Entry, Keys, OccupiedEntry, RandomState, VacantEntry, Values,
54};
55use std::collections::hash_set;
56use std::collections::{HashMap, HashSet};
57
58verus! {
59
60#[verifier::external_type_specification]
69#[verifier::external_body]
70pub struct ExDefaultHasher(DefaultHasher);
71
72impl View for DefaultHasher {
73 type V = Seq<Seq<u8>>;
74
75 #[verifier::external_body]
76 uninterp spec fn view(&self) -> Seq<Seq<u8>>;
77}
78
79pub trait DefaultHasherAdditionalSpecFns {
80 spec fn spec_finish(s: Seq<Seq<u8>>) -> u64;
81}
82
83impl DefaultHasherAdditionalSpecFns for DefaultHasher {
84 #[verifier::external_body]
85 uninterp spec fn spec_finish(s: Seq<Seq<u8>>) -> u64;
86}
87
88pub assume_specification[ DefaultHasher::new ]() -> (result: DefaultHasher)
90 ensures
91 result@ == Seq::<Seq<u8>>::empty(),
92;
93
94pub assume_specification[ DefaultHasher::write ](state: &mut DefaultHasher, bytes: &[u8])
96 ensures
97 final(state)@ == old(state)@.push(bytes@),
98;
99
100pub assume_specification[ DefaultHasher::finish ](state: &DefaultHasher) -> (result: u64)
102 ensures
103 result == DefaultHasher::spec_finish(state@),
104;
105
106#[verifier::external_body]
127pub uninterp spec fn obeys_key_model<Key: ?Sized>() -> bool;
128
129pub broadcast axiom fn axiom_key_model_implies_obeys_eq<Key: Hash + Eq + ?Sized>()
131 requires
132 #[trigger] obeys_key_model::<Key>(),
133 ensures
134 <Key as PartialEqSpec>::obeys_eq_spec(),
135 forall|a: &Key| #[trigger] a.eq_spec(a),
136 forall|a: &Key, b: &Key| #[trigger] a.eq_spec(b) <==> b.eq_spec(a),
137 forall|a: &Key, b: &Key, c: &Key|
138 a.eq_spec(b) && #[trigger] b.eq_spec(c) ==> #[trigger] a.eq_spec(c),
139;
140
141pub broadcast proof fn lemma_key_model_implies_obeys_eq<Key: Hash + Eq>()
142 requires
143 #[trigger] obeys_key_model::<Key>(),
144 ensures
145 crate::laws_eq::obeys_eq::<Key>(),
146{
147 broadcast use axiom_key_model_implies_obeys_eq;
148
149 reveal(crate::laws_eq::obeys_eq_spec_properties);
150}
151
152pub uninterp spec fn borrowed_key_hashing_matches<
158 Key: Borrow<Q> + Hash + Eq + ?Sized,
159 Q: Hash + Eq + ?Sized,
160>() -> bool;
161
162pub broadcast axiom fn axiom_borrowed_key_hashing_matches_self<Q: Hash + Eq + ?Sized>()
163 ensures
164 #[trigger] borrowed_key_hashing_matches::<Q, Q>(),
165;
166
167pub broadcast axiom fn axiom_borrowed_key_hashing_matches_ref<Q: Hash + Eq + ?Sized>()
168 ensures
169 #[trigger] borrowed_key_hashing_matches::<&Q, Q>(),
170;
171
172pub broadcast axiom fn axiom_borrowed_key_hashing_matches_box<Q: Hash + Eq + ?Sized, A: Allocator>()
173 ensures
174 #[trigger] borrowed_key_hashing_matches::<Box<Q, A>, Q>(),
175;
176
177pub broadcast axiom fn axiom_borrowed_key_hashing_matches_string()
178 ensures
179 #[trigger] borrowed_key_hashing_matches::<String, str>(),
180;
181
182pub broadcast axiom fn axiom_string_obeys_hash_table_key_model()
183 ensures
184 #[trigger] obeys_key_model::<String>(),
185;
186
187pub broadcast axiom fn axiom_str_obeys_hash_table_key_model()
188 ensures
189 #[trigger] obeys_key_model::<str>(),
190;
191
192pub broadcast proof fn axiom_bool_obeys_hash_table_key_model()
197 ensures
198 #[trigger] obeys_key_model::<bool>(),
199{
200 admit();
201}
202
203pub broadcast proof fn axiom_u8_obeys_hash_table_key_model()
204 ensures
205 #[trigger] obeys_key_model::<u8>(),
206{
207 admit();
208}
209
210pub broadcast proof fn axiom_u16_obeys_hash_table_key_model()
211 ensures
212 #[trigger] obeys_key_model::<u16>(),
213{
214 admit();
215}
216
217pub broadcast proof fn axiom_u32_obeys_hash_table_key_model()
218 ensures
219 #[trigger] obeys_key_model::<u32>(),
220{
221 admit();
222}
223
224pub broadcast proof fn axiom_u64_obeys_hash_table_key_model()
225 ensures
226 #[trigger] obeys_key_model::<u64>(),
227{
228 admit();
229}
230
231pub broadcast proof fn axiom_u128_obeys_hash_table_key_model()
232 ensures
233 #[trigger] obeys_key_model::<u128>(),
234{
235 admit();
236}
237
238pub broadcast proof fn axiom_usize_obeys_hash_table_key_model()
239 ensures
240 #[trigger] obeys_key_model::<usize>(),
241{
242 admit();
243}
244
245pub broadcast proof fn axiom_i8_obeys_hash_table_key_model()
246 ensures
247 #[trigger] obeys_key_model::<i8>(),
248{
249 admit();
250}
251
252pub broadcast proof fn axiom_i16_obeys_hash_table_key_model()
253 ensures
254 #[trigger] obeys_key_model::<i16>(),
255{
256 admit();
257}
258
259pub broadcast proof fn axiom_i32_obeys_hash_table_key_model()
260 ensures
261 #[trigger] obeys_key_model::<i32>(),
262{
263 admit();
264}
265
266pub broadcast proof fn axiom_i64_obeys_hash_table_key_model()
267 ensures
268 #[trigger] obeys_key_model::<i64>(),
269{
270 admit();
271}
272
273pub broadcast proof fn axiom_i128_obeys_hash_table_key_model()
274 ensures
275 #[trigger] obeys_key_model::<i128>(),
276{
277 admit();
278}
279
280pub broadcast proof fn axiom_isize_obeys_hash_table_key_model()
281 ensures
282 #[trigger] obeys_key_model::<isize>(),
283{
284 admit();
285}
286
287pub broadcast proof fn axiom_box_bool_obeys_hash_table_key_model()
288 ensures
289 #[trigger] obeys_key_model::<Box<bool>>(),
290{
291 admit();
292}
293
294pub broadcast proof fn axiom_box_integer_type_obeys_hash_table_key_model<Key: Integer + ?Sized>()
295 requires
296 obeys_key_model::<Key>(),
297 ensures
298 #[trigger] obeys_key_model::<Box<Key>>(),
299{
300 admit();
301}
302
303#[verifier::external_trait_specification]
312pub trait ExBuildHasher {
313 type ExternalTraitSpecificationFor: BuildHasher;
314
315 type Hasher: Hasher;
316}
317
318#[verifier::external_body]
332pub uninterp spec fn builds_valid_hashers<T: ?Sized>() -> bool;
333
334#[verifier::external_type_specification]
341#[verifier::external_body]
342pub struct ExRandomState(RandomState);
343
344pub broadcast proof fn axiom_random_state_builds_valid_hashers()
345 ensures
346 #[trigger] builds_valid_hashers::<RandomState>(),
347{
348 admit();
349}
350
351#[verifier::external_type_specification]
354#[verifier::external_body]
355#[verifier::accept_recursive_types(Key)]
356#[verifier::accept_recursive_types(Value)]
357pub struct ExKeys<'a, Key: 'a, Value: 'a>(Keys<'a, Key, Value>);
358
359pub uninterp spec fn into_iter_keys<'a, Key, Value>(i: Keys<'a, Key, Value>) -> Seq<Key>;
362
363impl<'a, K, V> super::iter::IteratorSpecImpl for Keys<'a, K, V> {
364 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
365 true
366 }
367
368 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
369
370 #[verifier::prophetic]
371 open spec fn produces(&self) -> Seq<bool> {
372 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
373 }
374
375 uninterp spec fn decrease(&self) -> Option<nat>;
376
377 open spec fn peek(&self, index: int) -> Option<Self::Item> {
378 if 0 <= index < into_iter_keys(*self).len() {
379 Some(&into_iter_keys(*self)[index])
380 } else {
381 None
382 }
383 }
384}
385
386#[verifier::external_type_specification]
389#[verifier::external_body]
390#[verifier::accept_recursive_types(Key)]
391#[verifier::accept_recursive_types(Value)]
392pub struct ExValues<'a, Key: 'a, Value: 'a>(Values<'a, Key, Value>);
393
394pub uninterp spec fn into_iter_values<'a, Key, Value>(i: Values<'a, Key, Value>) -> Seq<Value>;
397
398impl<'a, K, V> super::iter::IteratorSpecImpl for Values<'a, K, V> {
399 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
400 true
401 }
402
403 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
404
405 #[verifier::prophetic]
406 open spec fn produces(&self) -> Seq<bool> {
407 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
408 }
409
410 uninterp spec fn decrease(&self) -> Option<nat>;
411
412 open spec fn peek(&self, index: int) -> Option<Self::Item> {
413 if 0 <= index < into_iter_values(*self).len() {
414 Some(&into_iter_values(*self)[index])
415 } else {
416 None
417 }
418 }
419}
420
421#[verifier::external_type_specification]
424#[verifier::external_body]
425#[verifier::accept_recursive_types(Key)]
426#[verifier::accept_recursive_types(Value)]
427pub struct ExMapIter<'a, Key: 'a, Value: 'a>(hash_map::Iter<'a, Key, Value>);
428
429pub uninterp spec fn into_iter<'a, Key, Value>(i: hash_map::Iter<'a, Key, Value>) -> Seq<
432 (Key, Value),
433>;
434
435impl<'a, K, V> super::iter::IteratorSpecImpl for hash_map::Iter<'a, K, V> {
436 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
437 true
438 }
439
440 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
441
442 #[verifier::prophetic]
443 open spec fn produces(&self) -> Seq<bool> {
444 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
445 }
446
447 uninterp spec fn decrease(&self) -> Option<nat>;
448
449 open spec fn peek(&self, index: int) -> Option<Self::Item> {
450 if 0 <= index < into_iter(*self).len() {
451 let (k, v) = into_iter(*self)[index];
452 Some((&k, &v))
453 } else {
454 None
455 }
456 }
457}
458
459pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::iter ](
460 m: &'a HashMap<Key, Value, S, A>,
461) -> (iter: hash_map::Iter<'a, Key, Value>)
462 ensures
463 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
464 &&& IteratorSpec::remaining(&iter).len() == m@.dom().len()
465 &&& forall|i: int|
466 #![trigger m@.contains_key(*IteratorSpec::remaining(&iter)[i].0)]
467 #![trigger m@[*IteratorSpec::remaining(&iter)[i].0]]
468 0 <= i < IteratorSpec::remaining(&iter).len() ==> m@.contains_key(
469 *IteratorSpec::remaining(&iter)[i].0,
470 ) && m@[*IteratorSpec::remaining(&iter)[i].0] == *IteratorSpec::remaining(
471 &iter,
472 )[i].1
473 &&& forall|k: Key| #[trigger]
474 m@.contains_key(k) ==> IteratorSpec::remaining(&iter).contains((&k, &m@[k]))
475 &&& IteratorSpec::remaining(&iter).unref().to_set() == m@.kv_pairs()
476 &&& iter.remaining().no_duplicates()
477 &&& into_iter(iter) == IteratorSpec::remaining(&iter).unref()
478 &&& IteratorSpec::decrease(&iter) is Some
479 },
480;
481
482#[verifier::external_type_specification]
483#[verifier::external_body]
484#[verifier::accept_recursive_types(Key)]
485#[verifier::accept_recursive_types(Value)]
486#[verifier::reject_recursive_types(A)]
487pub struct ExMapIntoIter<Key, Value, A: Allocator>(hash_map::IntoIter<Key, Value, A>);
488
489pub uninterp spec fn into_iter_entries<Key, Value, A: Allocator>(
490 iter: hash_map::IntoIter<Key, Value, A>,
491) -> Seq<(Key, Value)>;
492
493impl<K, V, A: Allocator> super::iter::IteratorSpecImpl for hash_map::IntoIter<K, V, A> {
494 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
495 true
496 }
497
498 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
499
500 #[verifier::prophetic]
501 open spec fn produces(&self) -> Seq<bool> {
502 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
503 }
504
505 uninterp spec fn decrease(&self) -> Option<nat>;
506
507 open spec fn peek(&self, index: int) -> Option<Self::Item> {
508 if 0 <= index < into_iter_entries(*self).len() {
509 Some(into_iter_entries(*self)[index])
510 } else {
511 None
512 }
513 }
514}
515
516pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::into_iter ](
517 m: HashMap<Key, Value, S, A>,
518) -> (iter: hash_map::IntoIter<Key, Value, A>)
519 ensures
520 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> IteratorSpec::remaining(
521 &iter,
522 ).to_set() == m@.kv_pairs(),
523 iter.remaining().no_duplicates(),
524 into_iter_entries(iter) == IteratorSpec::remaining(&iter),
525 IteratorSpec::decrease(&iter) is Some,
526;
527
528#[verifier::external_type_specification]
540#[verifier::external_body]
541#[verifier::accept_recursive_types(Key)]
542#[verifier::accept_recursive_types(Value)]
543#[verifier::reject_recursive_types(S)]
544#[verifier::reject_recursive_types(A)]
545pub struct ExHashMap<Key, Value, S, A: Allocator>(HashMap<Key, Value, S, A>);
546
547pub trait HashMapAdditionalSpecFns<Key, Value>: View<V = Map<Key, Value>> {
548 spec fn spec_index(&self, k: Key) -> Value
549 recommends
550 self@.contains_key(k),
551 ;
552}
553
554impl<Key, Value, S, A: Allocator> HashMapAdditionalSpecFns<Key, Value> for HashMap<
555 Key,
556 Value,
557 S,
558 A,
559> {
560 #[verifier::inline]
561 open spec fn spec_index(&self, k: Key) -> Value {
562 self@.index(k)
563 }
564}
565
566#[verifier::opaque]
572pub open spec fn hash_map_deep_view_impl<
573 Key: DeepView,
574 Value: DeepView,
575 S,
576 A: core::alloc::Allocator,
577>(m: HashMap<Key, Value, S, A>) -> Map<Key::V, Value::V> {
578 Map::new(
579 m@.dom().map(|k: Key| k.deep_view()),
580 |dk: Key::V|
581 {
582 let k = choose|k: Key| m@.contains_key(k) && #[trigger] k.deep_view() == dk;
583 m@[k].deep_view()
584 },
585 )
586}
587
588pub broadcast proof fn lemma_hashmap_deepview_dom<K: DeepView, V: DeepView>(m: HashMap<K, V>)
589 ensures
590 #[trigger] m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()),
591{
592 reveal(hash_map_deep_view_impl);
593 broadcast use group_hash_axioms;
594 broadcast use crate::vstd::group_vstd_default;
595
596 assert(m.deep_view().dom() =~= m@.dom().map(|k: K| k.deep_view()));
597}
598
599pub broadcast proof fn lemma_hashmap_deepview_properties<K: DeepView, V: DeepView>(m: HashMap<K, V>)
600 requires
601 crate::relations::injective(|k: K| k.deep_view()),
602 ensures
603 #![trigger m.deep_view()]
604 forall|k: K| #[trigger]
606 m@.contains_key(k) ==> m.deep_view().contains_key(k.deep_view())
607 && m.deep_view()[k.deep_view()] == m@[k].deep_view(),
608 forall|dk: <K as DeepView>::V| #[trigger]
610 m.deep_view().contains_key(dk) ==> exists|k: K|
611 k.deep_view() == dk && #[trigger] m@.contains_key(k),
612{
613 reveal(hash_map_deep_view_impl);
614 broadcast use group_hash_axioms;
615 broadcast use crate::vstd::group_vstd_default;
616
617 lemma_hashmap_deepview_dom(m);
618 assert(m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()));
619 assert forall|k: K| #[trigger] m@.contains_key(k) implies m.deep_view().contains_key(
620 k.deep_view(),
621 ) && m.deep_view()[k.deep_view()] == m@[k].deep_view() by {
622 assert(m@.dom().contains(k));
623 assert(m@.dom().map(|k: K| k.deep_view()).contains(k.deep_view()));
624 assert(m.deep_view().dom().contains(k.deep_view()));
625 let k2 = choose|k2: K| m@.contains_key(k2) && #[trigger] k2.deep_view() == k.deep_view();
626 assert forall|k1: K, k2: K| #[trigger]
627 k1.deep_view() == #[trigger] k2.deep_view() implies k1 == k2 by {
628 let ghost k_deepview = |k: K| k.deep_view();
629 assert(crate::relations::injective(k_deepview));
630 assert(k_deepview(k1) == k_deepview(k2));
631 }
632 assert(k2 == k);
633 }
634 assert forall|dk: K::V| #[trigger] m.deep_view().contains_key(dk) implies exists|k: K|
635 k.deep_view() == dk && #[trigger] m@.contains_key(k) by {
636 assert(m.deep_view().dom().contains(dk));
637 assert(m@.dom().map(|k: K| k.deep_view()).contains(dk));
638 let k = choose|k: K| #[trigger] m@.dom().contains(k) && k.deep_view() == dk;
639 assert(m@.contains_key(k));
640 }
641}
642
643pub broadcast proof fn lemma_hashmap_deepview_values<K: DeepView, V: DeepView>(m: HashMap<K, V>)
644 requires
645 crate::relations::injective(|k: K| k.deep_view()),
646 ensures
647 #[trigger] m.deep_view().values() =~= m@.values().map(|v: V| v.deep_view()),
648{
649 reveal(hash_map_deep_view_impl);
650 broadcast use group_hash_axioms;
651 broadcast use lemma_hashmap_deepview_properties;
652 broadcast use crate::vstd::group_vstd_default;
653
654 let lhs = m.deep_view().values();
655 let rhs = m@.values().map(|v: V| v.deep_view());
656 assert forall|v: V::V| #[trigger] lhs.contains(v) implies rhs.contains(v) by {
657 let dk = choose|dk: K::V| #[trigger]
658 m.deep_view().contains_key(dk) && m.deep_view()[dk] == v;
659 let k = choose|k: K| #[trigger] m@.contains_key(k) && k.deep_view() == dk;
660 let ov = choose|ov: V| #[trigger] m@.contains_key(k) && m@[k] == ov && ov.deep_view() == v;
661 assert(v == ov.deep_view());
662 assert(m@.values().contains(ov));
663 }
664}
665
666pub uninterp spec fn spec_hash_map_len<Key, Value, S, A: Allocator>(
667 m: &HashMap<Key, Value, S, A>,
668) -> usize;
669
670pub broadcast proof fn axiom_spec_hash_map_len<Key, Value, S, A: Allocator>(
671 m: &HashMap<Key, Value, S, A>,
672)
673 ensures
674 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> #[trigger] spec_hash_map_len(m)
675 == m@.len(),
676{
677 admit();
678}
679
680#[verifier::when_used_as_spec(spec_hash_map_len)]
681pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::len ](
682 m: &HashMap<Key, Value, S, A>,
683) -> (len: usize)
684 ensures
685 len == spec_hash_map_len(m),
686;
687
688pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::capacity ](
689 m: &HashMap<Key, Value, S, A>,
690) -> (cap: usize)
691 ensures
692 cap >= spec_hash_map_len(m),
693;
694
695pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::is_empty ](
696 m: &HashMap<Key, Value, S, A>,
697) -> (res: bool)
698 ensures
699 res == m@.is_empty(),
700;
701
702pub assume_specification<K: Clone, V: Clone, S: Clone, A: Allocator + Clone>[ <HashMap::<
703 K,
704 V,
705 S,
706 A,
707> as Clone>::clone ](this: &HashMap<K, V, S, A>) -> (other: HashMap<K, V, S, A>)
708 ensures
709 other@.dom() == this@.dom(),
710 forall|key|
711 #![trigger other@.dom().contains(key)]
712 other@.dom().contains(key) ==> cloned(this@[key], #[trigger] other@[key]),
713;
714
715pub assume_specification<Key, Value>[ HashMap::<Key, Value>::new ]() -> (m: HashMap<
716 Key,
717 Value,
718 RandomState,
719>)
720 ensures
721 m@ == Map::<Key, Value>::empty(),
722;
723
724pub assume_specification<K, V, S: core::default::Default>[ <HashMap<
725 K,
726 V,
727 S,
728> as core::default::Default>::default ]() -> (m: HashMap<K, V, S>)
729 ensures
730 m@ == Map::<K, V>::empty(),
731;
732
733pub assume_specification<Key, Value>[ HashMap::<Key, Value>::with_capacity ](capacity: usize) -> (m:
734 HashMap<Key, Value, RandomState>)
735 ensures
736 m@ == Map::<Key, Value>::empty(),
737;
738
739pub assume_specification<Key, Value, S>[ HashMap::<Key, Value, S>::with_hasher ](
740 hash_builder: S,
741) -> (m: HashMap<Key, Value, S>)
742 ensures
743 m@ == Map::<Key, Value>::empty(),
744;
745
746pub assume_specification<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>[ HashMap::<
747 Key,
748 Value,
749 S,
750 A,
751>::reserve ](m: &mut HashMap<Key, Value, S, A>, additional: usize)
752 ensures
753 final(m)@ == old(m)@,
754;
755
756pub open spec fn hash_map_inv<Key: Eq + Hash, Value, S, A: Allocator>(
757 m: &HashMap<Key, Value, S, A>,
758) -> bool {
759 forall|k1: Key, k2: Key|
760 {
761 &&& #[trigger] m@.contains_key(k1)
762 &&& #[trigger] m@.contains_key(k2)
763 &&& k1 != k2
764 } ==> !k1.eq_spec(&k2)
765}
766
767pub open spec fn hash_map_insert_ensures<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>(
768 old_m: &HashMap<Key, Value, S, A>,
769 final_m: &HashMap<Key, Value, S, A>,
770 k: Key,
771 v: Value,
772 result: Option<Value>,
773) -> bool {
774 ({
775 &&& obeys_key_model::<Key>()
776 &&& builds_valid_hashers::<S>()
777 &&& hash_map_inv(old_m)
778 }) ==> {
779 &&& hash_map_inv(final_m)
780 &&& match result {
781 Some(old_value) => exists|stored_key: Key|
782 {
783 &&& #[trigger] old_m@.contains_key(stored_key)
784 &&& k.eq_spec(&stored_key)
785 &&& old_value == old_m@[stored_key]
786 &&& final_m@ == old_m@.insert(stored_key, v)
787 },
788 None => {
789 &&& forall|stored_key: Key| #[trigger]
790 old_m@.contains_key(stored_key) ==> !k.eq_spec(&stored_key)
791 &&& final_m@ == old_m@.insert(k, v)
792 },
793 }
794 }
795}
796
797pub assume_specification<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>[ HashMap::<
798 Key,
799 Value,
800 S,
801 A,
802>::insert ](m: &mut HashMap<Key, Value, S, A>, k: Key, v: Value) -> (result: Option<Value>)
803 ensures
804 hash_map_insert_ensures(old(m), final(m), k, v, result),
805;
806
807pub broadcast proof fn lemma_hash_map_insert_ensures_if_obeys_concrete_eq<
808 Key: Eq + Hash,
809 Value,
810 S: BuildHasher,
811 A: Allocator,
812>(
813 old_m: &HashMap<Key, Value, S, A>,
814 final_m: &HashMap<Key, Value, S, A>,
815 k: Key,
816 v: Value,
817 result: Option<Value>,
818)
819 requires
820 obeys_key_model::<Key>(),
821 builds_valid_hashers::<S>(),
822 obeys_concrete_eq::<Key>(),
823 hash_map_inv(old_m),
824 #[trigger] hash_map_insert_ensures(old_m, final_m, k, v, result),
825 ensures
826 final_m@ == old_m@.insert(k, v),
827 match result {
828 Some(old_value) => old_m@.contains_key(k) && old_value == old_m@[k],
829 None => !old_m@.contains_key(k),
830 },
831{
832 reveal(obeys_concrete_eq);
833}
834
835pub broadcast proof fn lemma_hash_map_insert_ensures_if_obeys_deep_eq<
836 Key: Eq + Hash + DeepView,
837 Value: DeepView,
838 S: BuildHasher,
839 A: Allocator,
840>(
841 old_m: &HashMap<Key, Value, S, A>,
842 final_m: &HashMap<Key, Value, S, A>,
843 k: Key,
844 v: Value,
845 result: Option<Value>,
846)
847 requires
848 obeys_key_model::<Key>(),
849 builds_valid_hashers::<S>(),
850 obeys_deep_eq::<Key>(),
851 hash_map_inv(old_m),
852 #[trigger] hash_map_insert_ensures(old_m, final_m, k, v, result),
853 ensures
854 final_m.deep_view() == old_m.deep_view().insert(k.deep_view(), v.deep_view()),
855 match result {
856 Some(old_value) => {
857 &&& old_m.deep_view().contains_key(k.deep_view())
858 &&& old_value.deep_view() == old_m.deep_view()[k.deep_view()]
859 },
860 None => !old_m.deep_view().contains_key(k.deep_view()),
861 },
862{
863 reveal(obeys_deep_eq);
864 broadcast use {
865 crate::map::group_map_lemmas,
866 crate::set::group_set_lemmas,
867 Set::lemma_map_contains,
868 };
869
870 reveal(hash_map_deep_view_impl);
871
872 let stored_key = match result {
873 Some(old_value) => choose|stored_key: Key|
874 {
875 &&& #[trigger] old_m@.contains_key(stored_key)
876 &&& k.eq_spec(&stored_key)
877 &&& old_value == old_m@[stored_key]
878 &&& final_m@ == old_m@.insert(stored_key, v)
879 },
880 None => k,
881 };
882 assert(final_m@.contains_key(stored_key));
883 assert_maps_equal!(
884 final_m.deep_view(),
885 old_m.deep_view().insert(k.deep_view(), v.deep_view()),
886 kd => {
887 if final_m.deep_view().contains_key(kd) && kd != k.deep_view() {
888 let key = choose|key: Key|
889 final_m@.contains_key(key) && #[trigger] key.deep_view() == kd;
890 assert(old_m@.contains_key(key));
891 }
892 if old_m.deep_view().contains_key(kd) {
893 let key = choose|key: Key|
894 old_m@.contains_key(key) && #[trigger] key.deep_view() == kd;
895 assert(final_m@.contains_key(key));
896 }
897 }
898 );
899}
900
901pub open spec fn hash_map_contains_key_ensures<
902 Key: Borrow<Q> + Hash + Eq,
903 Value,
904 S: BuildHasher,
905 A: Allocator,
906 Q: Hash + Eq + ?Sized,
907>(m: &HashMap<Key, Value, S, A>, k: &Q, result: bool) -> bool {
908 ({
909 &&& obeys_key_model::<Key>()
910 &&& obeys_key_model::<Q>()
911 &&& builds_valid_hashers::<S>()
912 &&& <Key as BorrowSpec<Q>>::obeys_borrow_spec()
913 &&& hash_map_inv(m)
914 }) ==> {
915 result == exists|key: Key|
916 {
917 &&& #[trigger] m@.contains_key(key)
918 &&& k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key))
919 }
920 }
921}
922
923pub assume_specification<
924 Key: Borrow<Q> + Hash + Eq,
925 Value,
926 S: BuildHasher,
927 A: Allocator,
928 Q: Hash + Eq + ?Sized,
929>[ HashMap::<Key, Value, S, A>::contains_key::<Q> ](
930 m: &HashMap<Key, Value, S, A>,
931 k: &Q,
932) -> (result: bool)
933 requires
934 borrowed_key_hashing_matches::<Key, Q>(),
935 ensures
936 hash_map_contains_key_ensures(m, k, result),
937;
938
939pub broadcast proof fn lemma_hash_map_contains_key_ensures_if_obeys_concrete_eq<
940 Key: Eq + Hash,
941 Value,
942 S: BuildHasher,
943 A: Allocator,
944>(m: &HashMap<Key, Value, S, A>, k: &Key, result: bool)
945 requires
946 obeys_key_model::<Key>(),
947 builds_valid_hashers::<S>(),
948 obeys_concrete_eq::<Key>(),
949 hash_map_inv(m),
950 #[trigger] hash_map_contains_key_ensures(m, k, result),
951 ensures
952 result == m@.contains_key(*k),
953{
954 reveal(obeys_concrete_eq);
955}
956
957pub broadcast proof fn lemma_hash_map_contains_key_ensures_if_obeys_deep_eq<
958 Key: Eq + Hash + DeepView,
959 Value: DeepView,
960 S: BuildHasher,
961 A: Allocator,
962>(m: &HashMap<Key, Value, S, A>, k: &Key, result: bool)
963 requires
964 obeys_key_model::<Key>(),
965 builds_valid_hashers::<S>(),
966 obeys_deep_eq::<Key>(),
967 hash_map_inv(m),
968 #[trigger] hash_map_contains_key_ensures(m, k, result),
969 ensures
970 result == m.deep_view().contains_key(k.deep_view()),
971{
972 reveal(obeys_deep_eq);
973 broadcast use {
974 crate::map::group_map_lemmas,
975 crate::set::group_set_lemmas,
976 Set::lemma_map_contains,
977 };
978
979 reveal(hash_map_deep_view_impl);
980
981 if result {
982 let key = choose|key: Key|
983 {
984 &&& #[trigger] m@.contains_key(key)
985 &&& k.eq_spec(&key)
986 };
987 assert(m.deep_view().contains_key(key.deep_view()));
988 }
989 if m.deep_view().contains_key(k.deep_view()) {
990 let key = choose|key: Key|
991 m@.contains_key(key) && #[trigger] key.deep_view() == k.deep_view();
992 assert(k.eq_spec(&key));
993 }
994}
995
996pub open spec fn hash_map_get_ensures<
997 Key: Borrow<Q> + Hash + Eq,
998 Value,
999 S: BuildHasher,
1000 A: Allocator,
1001 Q: Hash + Eq + ?Sized,
1002>(m: &HashMap<Key, Value, S, A>, k: &Q, result: Option<&Value>) -> bool {
1003 ({
1004 &&& obeys_key_model::<Key>()
1005 &&& obeys_key_model::<Q>()
1006 &&& builds_valid_hashers::<S>()
1007 &&& <Key as BorrowSpec<Q>>::obeys_borrow_spec()
1008 &&& hash_map_inv(m)
1009 }) ==> {
1010 match result {
1011 Some(v) => exists|key: Key|
1012 {
1013 &&& #[trigger] m@.contains_key(key)
1014 &&& k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key))
1015 &&& m@[key] == *v
1016 },
1017 None => forall|key: Key| #[trigger]
1018 m@.contains_key(key) ==> !k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key)),
1019 }
1020 }
1021}
1022
1023pub assume_specification<
1024 'a,
1025 Key: Borrow<Q> + Hash + Eq,
1026 Value,
1027 S: BuildHasher,
1028 A: Allocator,
1029 Q: Hash + Eq + ?Sized,
1030>[ HashMap::<Key, Value, S, A>::get::<Q> ](m: &'a HashMap<Key, Value, S, A>, k: &Q) -> (result:
1031 Option<&'a Value>)
1032 requires
1033 borrowed_key_hashing_matches::<Key, Q>(),
1034 ensures
1035 hash_map_get_ensures(m, k, result),
1036;
1037
1038pub broadcast proof fn lemma_hash_map_get_ensures_if_obeys_concrete_eq<
1039 Key: Eq + Hash,
1040 Value,
1041 S: BuildHasher,
1042 A: Allocator,
1043>(m: &HashMap<Key, Value, S, A>, k: &Key, result: Option<&Value>)
1044 requires
1045 obeys_key_model::<Key>(),
1046 builds_valid_hashers::<S>(),
1047 obeys_concrete_eq::<Key>(),
1048 hash_map_inv(m),
1049 #[trigger] hash_map_get_ensures(m, k, result),
1050 ensures
1051 match result {
1052 Some(v) => m@.contains_key(*k) && *v == m@[*k],
1053 None => !m@.contains_key(*k),
1054 },
1055{
1056 reveal(obeys_concrete_eq);
1057}
1058
1059pub broadcast proof fn lemma_hash_map_get_ensures_if_obeys_deep_eq<
1060 Key: Eq + Hash + DeepView,
1061 Value: DeepView,
1062 S: BuildHasher,
1063 A: Allocator,
1064>(m: &HashMap<Key, Value, S, A>, k: &Key, result: Option<&Value>)
1065 requires
1066 obeys_key_model::<Key>(),
1067 builds_valid_hashers::<S>(),
1068 obeys_deep_eq::<Key>(),
1069 hash_map_inv(m),
1070 #[trigger] hash_map_get_ensures(m, k, result),
1071 ensures
1072 match result {
1073 Some(v) => {
1074 &&& m.deep_view().contains_key(k.deep_view())
1075 &&& v.deep_view() == m.deep_view()[k.deep_view()]
1076 },
1077 None => !m.deep_view().contains_key(k.deep_view()),
1078 },
1079{
1080 reveal(obeys_deep_eq);
1081 broadcast use {
1082 crate::map::group_map_lemmas,
1083 crate::set::group_set_lemmas,
1084 Set::lemma_map_contains,
1085 };
1086
1087 reveal(hash_map_deep_view_impl);
1088
1089 match result {
1090 Some(v) => {
1091 let stored_key = choose|key: Key|
1092 {
1093 &&& #[trigger] m@.contains_key(key)
1094 &&& k.eq_spec(&key)
1095 &&& m@[key] == *v
1096 };
1097 assert(m.deep_view().contains_key(k.deep_view()));
1098 let key = choose|key: Key|
1099 m@.contains_key(key) && #[trigger] key.deep_view() == k.deep_view();
1100 assert(key == stored_key);
1101 },
1102 None => {
1103 if m.deep_view().contains_key(k.deep_view()) {
1104 let key = choose|key: Key|
1105 m@.contains_key(key) && #[trigger] key.deep_view() == k.deep_view();
1106 assert(k.eq_spec(&key));
1107 }
1108 },
1109 }
1110}
1111
1112pub open spec fn hash_map_remove_ensures<
1113 Key: Borrow<Q> + Hash + Eq,
1114 Value,
1115 S: BuildHasher,
1116 A: Allocator,
1117 Q: Hash + Eq + ?Sized,
1118>(
1119 old_m: &HashMap<Key, Value, S, A>,
1120 final_m: &HashMap<Key, Value, S, A>,
1121 k: &Q,
1122 result: Option<Value>,
1123) -> bool {
1124 ({
1125 &&& obeys_key_model::<Key>()
1126 &&& obeys_key_model::<Q>()
1127 &&& builds_valid_hashers::<S>()
1128 &&& <Key as BorrowSpec<Q>>::obeys_borrow_spec()
1129 &&& hash_map_inv(old_m)
1130 }) ==> {
1131 &&& hash_map_inv(final_m)
1132 &&& match result {
1133 Some(v) => exists|key: Key|
1134 {
1135 &&& #[trigger] old_m@.contains_key(key)
1136 &&& k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key))
1137 &&& old_m@[key] == v
1138 &&& final_m@ == old_m@.remove(key)
1139 },
1140 None => {
1141 &&& forall|key: Key| #[trigger]
1142 old_m@.contains_key(key) ==> !k.eq_spec(
1143 <Key as BorrowSpec<Q>>::borrow_spec(&key),
1144 )
1145 &&& final_m@ == old_m@
1146 },
1147 }
1148 }
1149}
1150
1151pub assume_specification<
1152 Key: Borrow<Q> + Hash + Eq,
1153 Value,
1154 S: BuildHasher,
1155 A: Allocator,
1156 Q: Hash + Eq + ?Sized,
1157>[ HashMap::<Key, Value, S, A>::remove::<Q> ](m: &mut HashMap<Key, Value, S, A>, k: &Q) -> (result:
1158 Option<Value>)
1159 requires
1160 borrowed_key_hashing_matches::<Key, Q>(),
1161 ensures
1162 hash_map_remove_ensures(old(m), final(m), k, result),
1163;
1164
1165pub broadcast proof fn lemma_hash_map_remove_ensures_if_obeys_concrete_eq<
1166 Key: Eq + Hash,
1167 Value,
1168 S: BuildHasher,
1169 A: Allocator,
1170>(
1171 old_m: &HashMap<Key, Value, S, A>,
1172 final_m: &HashMap<Key, Value, S, A>,
1173 k: &Key,
1174 result: Option<Value>,
1175)
1176 requires
1177 obeys_key_model::<Key>(),
1178 builds_valid_hashers::<S>(),
1179 obeys_concrete_eq::<Key>(),
1180 hash_map_inv(old_m),
1181 #[trigger] hash_map_remove_ensures(old_m, final_m, k, result),
1182 ensures
1183 final_m@ == old_m@.remove(*k),
1184 match result {
1185 Some(v) => old_m@.contains_key(*k) && v == old_m@[*k],
1186 None => !old_m@.contains_key(*k),
1187 },
1188{
1189 reveal(obeys_concrete_eq);
1190 broadcast use {crate::map::group_map_lemmas, crate::set::group_set_lemmas};
1191
1192 if result is None {
1193 assert(!old_m@.contains_key(*k));
1194 assert(old_m@.remove(*k) =~= old_m@);
1195 }
1196}
1197
1198pub broadcast proof fn lemma_hash_map_remove_ensures_if_obeys_deep_eq<
1199 Key: Eq + Hash + DeepView,
1200 Value: DeepView,
1201 S: BuildHasher,
1202 A: Allocator,
1203>(
1204 old_m: &HashMap<Key, Value, S, A>,
1205 final_m: &HashMap<Key, Value, S, A>,
1206 k: &Key,
1207 result: Option<Value>,
1208)
1209 requires
1210 obeys_key_model::<Key>(),
1211 builds_valid_hashers::<S>(),
1212 obeys_deep_eq::<Key>(),
1213 hash_map_inv(old_m),
1214 #[trigger] hash_map_remove_ensures(old_m, final_m, k, result),
1215 ensures
1216 final_m.deep_view() == old_m.deep_view().remove(k.deep_view()),
1217 match result {
1218 Some(v) => {
1219 &&& old_m.deep_view().contains_key(k.deep_view())
1220 &&& v.deep_view() == old_m.deep_view()[k.deep_view()]
1221 },
1222 None => !old_m.deep_view().contains_key(k.deep_view()),
1223 },
1224{
1225 reveal(obeys_deep_eq);
1226 broadcast use {
1227 crate::map::group_map_lemmas,
1228 crate::set::group_set_lemmas,
1229 Set::lemma_map_contains,
1230 };
1231
1232 reveal(hash_map_deep_view_impl);
1233
1234 let stored_key = match result {
1235 Some(v) => choose|key: Key|
1236 {
1237 &&& #[trigger] old_m@.contains_key(key)
1238 &&& k.eq_spec(&key)
1239 &&& old_m@[key] == v
1240 &&& final_m@ == old_m@.remove(key)
1241 },
1242 None => *k,
1243 };
1244 match result {
1245 Some(v) => {
1246 assert(old_m.deep_view().contains_key(k.deep_view()));
1247 let key = choose|key: Key|
1248 old_m@.contains_key(key) && #[trigger] key.deep_view() == k.deep_view();
1249 assert(key == stored_key);
1250 },
1251 None => {
1252 if old_m.deep_view().contains_key(k.deep_view()) {
1253 let key = choose|key: Key|
1254 old_m@.contains_key(key) && #[trigger] key.deep_view() == k.deep_view();
1255 assert(k.eq_spec(&key));
1256 }
1257 },
1258 }
1259
1260 assert_maps_equal!(
1261 final_m.deep_view(),
1262 old_m.deep_view().remove(k.deep_view()),
1263 kd => {
1264 if final_m.deep_view().contains_key(kd) {
1265 let key = choose|key: Key|
1266 final_m@.contains_key(key) && #[trigger] key.deep_view() == kd;
1267 assert(old_m@.contains_key(key));
1268 assert(key.deep_view() != k.deep_view());
1269 }
1270 if old_m.deep_view().contains_key(kd) && kd != k.deep_view() {
1271 let key = choose|key: Key|
1272 old_m@.contains_key(key) && #[trigger] key.deep_view() == kd;
1273 assert(final_m@.contains_key(key));
1274 }
1275 }
1276 );
1277}
1278
1279pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::clear ](
1280 m: &mut HashMap<Key, Value, S, A>,
1281)
1282 ensures
1283 final(m)@ == Map::<Key, Value>::empty(),
1284;
1285
1286pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::keys ](
1287 m: &'a HashMap<Key, Value, S, A>,
1288) -> (keys: Keys<'a, Key, Value>)
1289 ensures
1290 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1291 &&& IteratorSpec::remaining(&keys).unref().to_set() == m@.dom()
1292 &&& IteratorSpec::remaining(&keys).no_duplicates()
1293 &&& IteratorSpec::remaining(&keys).len() == m@.dom().len()
1294 &&& into_iter_keys(keys) == IteratorSpec::remaining(&keys).unref()
1295 &&& IteratorSpec::decrease(&keys) is Some
1296 },
1297;
1298
1299pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::values ](
1300 m: &'a HashMap<Key, Value, S, A>,
1301) -> (values: Values<'a, Key, Value>)
1302 ensures
1303 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1304 &&& IteratorSpec::remaining(&values).unref().to_set() == m@.values()
1305 &&& IteratorSpec::remaining(&values).len() == m@.dom().len()
1306 &&& into_iter_values(values) == IteratorSpec::remaining(&values).unref()
1307 &&& IteratorSpec::decrease(&values) is Some
1308 },
1309;
1310
1311pub broadcast proof fn axiom_hashmap_decreases<Key, Value, S>(m: HashMap<Key, Value, S>)
1312 ensures
1313 #[trigger] (decreases_to!(m => m@)),
1314{
1315 admit();
1316}
1317
1318#[verifier::external_type_specification]
1321#[verifier::external_body]
1322#[verifier::accept_recursive_types(Key)]
1323pub struct ExSetIter<'a, Key: 'a>(hash_set::Iter<'a, Key>);
1324
1325pub uninterp spec fn into_iter_hash_keys<'a, Key>(i: hash_set::Iter::<'a, Key>) -> Seq<Key>;
1328
1329impl<'a, K> super::iter::IteratorSpecImpl for hash_set::Iter::<'a, K> {
1330 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
1331 true
1332 }
1333
1334 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
1335
1336 #[verifier::prophetic]
1337 open spec fn produces(&self) -> Seq<bool> {
1338 Seq::new(IteratorSpec::remaining(self).len(), |i: int| true)
1339 }
1340
1341 uninterp spec fn decrease(&self) -> Option<nat>;
1342
1343 open spec fn peek(&self, index: int) -> Option<Self::Item> {
1344 if 0 <= index < into_iter_hash_keys(*self).len() {
1345 Some(&into_iter_hash_keys(*self)[index])
1346 } else {
1347 None
1348 }
1349 }
1350}
1351
1352#[verifier::external_type_specification]
1364#[verifier::external_body]
1365#[verifier::accept_recursive_types(Key)]
1366#[verifier::reject_recursive_types(S)]
1367#[verifier::reject_recursive_types(A)]
1368pub struct ExHashSet<Key, S, A: Allocator>(HashSet<Key, S, A>);
1369
1370pub uninterp spec fn spec_hash_set_len<Key, S, A: Allocator>(m: &HashSet<Key, S, A>) -> usize;
1371
1372pub broadcast proof fn axiom_spec_hash_set_len<Key, S, A: Allocator>(m: &HashSet<Key, S, A>)
1373 ensures
1374 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> #[trigger] spec_hash_set_len(m)
1375 == m@.len(),
1376{
1377 admit();
1378}
1379
1380#[verifier::when_used_as_spec(spec_hash_set_len)]
1381pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::len ](
1382 m: &HashSet<Key, S, A>,
1383) -> (len: usize)
1384 ensures
1385 len == spec_hash_set_len(m),
1386;
1387
1388pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::is_empty ](
1389 m: &HashSet<Key, S, A>,
1390) -> (res: bool)
1391 ensures
1392 res == m@.is_empty(),
1393;
1394
1395pub assume_specification<Key>[ HashSet::<Key>::new ]() -> (m: HashSet<Key, RandomState>)
1396 ensures
1397 m@ == Set::<Key>::empty(),
1398;
1399
1400pub assume_specification<T, S: core::default::Default>[ <HashSet<
1401 T,
1402 S,
1403> as core::default::Default>::default ]() -> (m: HashSet<T, S>)
1404 ensures
1405 m@ == Set::<T>::empty(),
1406;
1407
1408pub assume_specification<Key>[ HashSet::<Key>::with_capacity ](capacity: usize) -> (m: HashSet<
1409 Key,
1410 RandomState,
1411>)
1412 ensures
1413 m@ == Set::<Key>::empty(),
1414;
1415
1416pub assume_specification<Key, S>[ HashSet::<Key, S>::with_hasher ](hash_builder: S) -> (m: HashSet<
1417 Key,
1418 S,
1419>)
1420 ensures
1421 m@ == Set::<Key>::empty(),
1422;
1423
1424pub assume_specification<Key, S>[ HashSet::<Key, S>::with_capacity_and_hasher ](
1425 capacity: usize,
1426 hash_builder: S,
1427) -> (m: HashSet<Key, S>)
1428 ensures
1429 m@ == Set::<Key>::empty(),
1430;
1431
1432pub assume_specification<Key: Eq + Hash, S: BuildHasher, A: Allocator>[ HashSet::<
1433 Key,
1434 S,
1435 A,
1436>::reserve ](m: &mut HashSet<Key, S, A>, additional: usize)
1437 ensures
1438 final(m)@ == old(m)@,
1439;
1440
1441pub open spec fn hash_set_inv<Key: Eq + Hash, S, A: Allocator>(m: &HashSet<Key, S, A>) -> bool {
1442 forall|k1: Key, k2: Key|
1443 {
1444 &&& #[trigger] m@.contains(k1)
1445 &&& #[trigger] m@.contains(k2)
1446 &&& k1 != k2
1447 } ==> !k1.eq_spec(&k2)
1448}
1449
1450pub open spec fn hash_set_insert_ensures<Key: Eq + Hash, S: BuildHasher, A: Allocator>(
1451 old_m: &HashSet<Key, S, A>,
1452 final_m: &HashSet<Key, S, A>,
1453 k: Key,
1454 result: bool,
1455) -> bool {
1456 ({
1457 &&& obeys_key_model::<Key>()
1458 &&& builds_valid_hashers::<S>()
1459 &&& hash_set_inv(old_m)
1460 }) ==> {
1461 &&& hash_set_inv(final_m)
1462 &&& if result {
1463 &&& forall|stored_key: Key| #[trigger]
1464 old_m@.contains(stored_key) ==> !k.eq_spec(&stored_key)
1465 &&& final_m@ == old_m@.insert(k)
1466 } else {
1467 &&& exists|stored_key: Key| #[trigger]
1468 old_m@.contains(stored_key) && k.eq_spec(&stored_key)
1469 &&& final_m@ == old_m@
1470 }
1471 }
1472}
1473
1474pub assume_specification<Key: Eq + Hash, S: BuildHasher, A: Allocator>[ HashSet::<
1475 Key,
1476 S,
1477 A,
1478>::insert ](m: &mut HashSet<Key, S, A>, k: Key) -> (result: bool)
1479 ensures
1480 hash_set_insert_ensures(old(m), final(m), k, result),
1481;
1482
1483pub broadcast proof fn lemma_hash_set_insert_ensures_if_obeys_concrete_eq<
1484 Key: Eq + Hash,
1485 S: BuildHasher,
1486 A: Allocator,
1487>(old_m: &HashSet<Key, S, A>, final_m: &HashSet<Key, S, A>, k: Key, result: bool)
1488 requires
1489 obeys_key_model::<Key>(),
1490 builds_valid_hashers::<S>(),
1491 obeys_concrete_eq::<Key>(),
1492 hash_set_inv(old_m),
1493 #[trigger] hash_set_insert_ensures(old_m, final_m, k, result),
1494 ensures
1495 final_m@ == old_m@.insert(k),
1496 result == !old_m@.contains(k),
1497{
1498 reveal(obeys_concrete_eq);
1499 broadcast use crate::set::group_set_lemmas;
1500
1501 assert(k.eq_spec(&k));
1502 if !result {
1503 assert(old_m@.contains(k));
1504 assert(old_m@.insert(k) =~= old_m@);
1505 }
1506}
1507
1508pub broadcast proof fn lemma_hash_set_insert_ensures_if_obeys_deep_eq<
1509 Key: Eq + Hash + DeepView,
1510 S: BuildHasher,
1511 A: Allocator,
1512>(old_m: &HashSet<Key, S, A>, final_m: &HashSet<Key, S, A>, k: Key, result: bool)
1513 requires
1514 obeys_key_model::<Key>(),
1515 builds_valid_hashers::<S>(),
1516 obeys_deep_eq::<Key>(),
1517 hash_set_inv(old_m),
1518 #[trigger] hash_set_insert_ensures(old_m, final_m, k, result),
1519 ensures
1520 final_m.deep_view() == old_m.deep_view().insert(k.deep_view()),
1521 result == !old_m.deep_view().contains(k.deep_view()),
1522{
1523 reveal(obeys_deep_eq);
1524 broadcast use {
1525 crate::set::group_set_lemmas,
1526 Set::lemma_map_contains,
1527 Set::lemma_set_map_insert_commute,
1528 };
1529
1530 if result {
1531 assert(!old_m.deep_view().contains(k.deep_view())) by {
1532 if old_m.deep_view().contains(k.deep_view()) {
1533 let stored_key = choose|stored_key: Key|
1534 old_m@.contains(stored_key) && #[trigger] stored_key.deep_view()
1535 == k.deep_view();
1536 assert(k.eq_spec(&stored_key));
1537 }
1538 }
1539 } else {
1540 let stored_key = choose|stored_key: Key| #[trigger]
1541 old_m@.contains(stored_key) && k.eq_spec(&stored_key);
1542 assert(stored_key.deep_view() == k.deep_view());
1543 assert(old_m.deep_view().contains(k.deep_view()));
1544 }
1545 assert(final_m.deep_view() =~= old_m.deep_view().insert(k.deep_view()));
1546}
1547
1548pub open spec fn hash_set_contains_ensures<
1549 Key: Borrow<Q> + Hash + Eq,
1550 S: BuildHasher,
1551 A: Allocator,
1552 Q: Hash + Eq + ?Sized,
1553>(m: &HashSet<Key, S, A>, k: &Q, result: bool) -> bool {
1554 ({
1555 &&& obeys_key_model::<Key>()
1556 &&& obeys_key_model::<Q>()
1557 &&& builds_valid_hashers::<S>()
1558 &&& <Key as BorrowSpec<Q>>::obeys_borrow_spec()
1559 &&& hash_set_inv(m)
1560 }) ==> {
1561 result == exists|key: Key|
1562 {
1563 &&& #[trigger] m@.contains(key)
1564 &&& k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key))
1565 }
1566 }
1567}
1568
1569pub assume_specification<
1570 Key: Borrow<Q> + Hash + Eq,
1571 S: BuildHasher,
1572 A: Allocator,
1573 Q: Hash + Eq + ?Sized,
1574>[ HashSet::<Key, S, A>::contains ](m: &HashSet<Key, S, A>, k: &Q) -> (result: bool)
1575 requires
1576 borrowed_key_hashing_matches::<Key, Q>(),
1577 ensures
1578 hash_set_contains_ensures(m, k, result),
1579;
1580
1581pub broadcast proof fn lemma_hash_set_contains_ensures_if_obeys_concrete_eq<
1582 Key: Eq + Hash,
1583 S: BuildHasher,
1584 A: Allocator,
1585>(m: &HashSet<Key, S, A>, k: &Key, result: bool)
1586 requires
1587 obeys_key_model::<Key>(),
1588 builds_valid_hashers::<S>(),
1589 obeys_concrete_eq::<Key>(),
1590 hash_set_inv(m),
1591 #[trigger] hash_set_contains_ensures(m, k, result),
1592 ensures
1593 result == m@.contains(*k),
1594{
1595 reveal(obeys_concrete_eq);
1596}
1597
1598pub broadcast proof fn lemma_hash_set_contains_ensures_if_obeys_deep_eq<
1599 Key: Eq + Hash + DeepView,
1600 S: BuildHasher,
1601 A: Allocator,
1602>(m: &HashSet<Key, S, A>, k: &Key, result: bool)
1603 requires
1604 obeys_key_model::<Key>(),
1605 builds_valid_hashers::<S>(),
1606 obeys_deep_eq::<Key>(),
1607 hash_set_inv(m),
1608 #[trigger] hash_set_contains_ensures(m, k, result),
1609 ensures
1610 result == m.deep_view().contains(k.deep_view()),
1611{
1612 reveal(obeys_deep_eq);
1613 broadcast use {crate::set::group_set_lemmas, Set::lemma_map_contains};
1614
1615 if result {
1616 let key = choose|key: Key| #[trigger] m@.contains(key) && k.eq_spec(&key);
1617 assert(m.deep_view().contains(key.deep_view()));
1618 }
1619 if m.deep_view().contains(k.deep_view()) {
1620 let key = choose|key: Key| m@.contains(key) && #[trigger] key.deep_view() == k.deep_view();
1621 assert(k.eq_spec(&key));
1622 }
1623}
1624
1625pub open spec fn hash_set_get_ensures<
1626 Key: Borrow<Q> + Hash + Eq,
1627 S: BuildHasher,
1628 A: Allocator,
1629 Q: Hash + Eq + ?Sized,
1630>(m: &HashSet<Key, S, A>, k: &Q, result: Option<&Key>) -> bool {
1631 ({
1632 &&& obeys_key_model::<Key>()
1633 &&& obeys_key_model::<Q>()
1634 &&& builds_valid_hashers::<S>()
1635 &&& <Key as BorrowSpec<Q>>::obeys_borrow_spec()
1636 &&& hash_set_inv(m)
1637 }) ==> {
1638 match result {
1639 Some(key) => {
1640 &&& m@.contains(*key)
1641 &&& k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(key))
1642 },
1643 None => forall|key: Key| #[trigger]
1644 m@.contains(key) ==> !k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key)),
1645 }
1646 }
1647}
1648
1649pub assume_specification<
1650 'a,
1651 Key: Borrow<Q> + Hash + Eq,
1652 S: BuildHasher,
1653 A: Allocator,
1654 Q: Hash + Eq + ?Sized,
1655>[ HashSet::<Key, S, A>::get::<Q> ](m: &'a HashSet<Key, S, A>, k: &Q) -> (result: Option<&'a Key>)
1656 requires
1657 borrowed_key_hashing_matches::<Key, Q>(),
1658 ensures
1659 hash_set_get_ensures(m, k, result),
1660;
1661
1662pub broadcast proof fn lemma_hash_set_get_ensures_if_obeys_concrete_eq<
1663 Key: Eq + Hash,
1664 S: BuildHasher,
1665 A: Allocator,
1666>(m: &HashSet<Key, S, A>, k: &Key, result: Option<&Key>)
1667 requires
1668 obeys_key_model::<Key>(),
1669 builds_valid_hashers::<S>(),
1670 obeys_concrete_eq::<Key>(),
1671 hash_set_inv(m),
1672 #[trigger] hash_set_get_ensures(m, k, result),
1673 ensures
1674 match result {
1675 Some(key) => m@.contains(*key) && *key == *k,
1676 None => !m@.contains(*k),
1677 },
1678{
1679 reveal(obeys_concrete_eq);
1680}
1681
1682pub broadcast proof fn lemma_hash_set_get_ensures_if_obeys_deep_eq<
1683 Key: Eq + Hash + DeepView,
1684 S: BuildHasher,
1685 A: Allocator,
1686>(m: &HashSet<Key, S, A>, k: &Key, result: Option<&Key>)
1687 requires
1688 obeys_key_model::<Key>(),
1689 builds_valid_hashers::<S>(),
1690 obeys_deep_eq::<Key>(),
1691 hash_set_inv(m),
1692 #[trigger] hash_set_get_ensures(m, k, result),
1693 ensures
1694 match result {
1695 Some(key) => {
1696 &&& m@.contains(*key)
1697 &&& m.deep_view().contains(k.deep_view())
1698 &&& key.deep_view() == k.deep_view()
1699 },
1700 None => !m.deep_view().contains(k.deep_view()),
1701 },
1702{
1703 reveal(obeys_deep_eq);
1704 broadcast use {crate::set::group_set_lemmas, Set::lemma_map_contains};
1705
1706 match result {
1707 Some(key) => {
1708 assert(m.deep_view().contains(key.deep_view()));
1709 },
1710 None => {
1711 if m.deep_view().contains(k.deep_view()) {
1712 let key = choose|key: Key|
1713 m@.contains(key) && #[trigger] key.deep_view() == k.deep_view();
1714 assert(k.eq_spec(&key));
1715 }
1716 },
1717 }
1718}
1719
1720pub open spec fn hash_set_remove_ensures<
1721 Key: Borrow<Q> + Hash + Eq,
1722 S: BuildHasher,
1723 A: Allocator,
1724 Q: Hash + Eq + ?Sized,
1725>(old_m: &HashSet<Key, S, A>, final_m: &HashSet<Key, S, A>, k: &Q, result: bool) -> bool {
1726 ({
1727 &&& obeys_key_model::<Key>()
1728 &&& obeys_key_model::<Q>()
1729 &&& builds_valid_hashers::<S>()
1730 &&& <Key as BorrowSpec<Q>>::obeys_borrow_spec()
1731 &&& hash_set_inv(old_m)
1732 }) ==> {
1733 &&& hash_set_inv(final_m)
1734 &&& if result {
1735 exists|key: Key|
1736 {
1737 &&& #[trigger] old_m@.contains(key)
1738 &&& k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key))
1739 &&& final_m@ == old_m@.remove(key)
1740 }
1741 } else {
1742 &&& forall|key: Key| #[trigger]
1743 old_m@.contains(key) ==> !k.eq_spec(<Key as BorrowSpec<Q>>::borrow_spec(&key))
1744 &&& final_m@ == old_m@
1745 }
1746 }
1747}
1748
1749pub assume_specification<
1750 Key: Borrow<Q> + Hash + Eq,
1751 S: BuildHasher,
1752 A: Allocator,
1753 Q: Hash + Eq + ?Sized,
1754>[ HashSet::<Key, S, A>::remove::<Q> ](m: &mut HashSet<Key, S, A>, k: &Q) -> (result: bool)
1755 requires
1756 borrowed_key_hashing_matches::<Key, Q>(),
1757 ensures
1758 hash_set_remove_ensures(old(m), final(m), k, result),
1759;
1760
1761pub broadcast proof fn lemma_hash_set_remove_ensures_if_obeys_concrete_eq<
1762 Key: Eq + Hash,
1763 S: BuildHasher,
1764 A: Allocator,
1765>(old_m: &HashSet<Key, S, A>, final_m: &HashSet<Key, S, A>, k: &Key, result: bool)
1766 requires
1767 obeys_key_model::<Key>(),
1768 builds_valid_hashers::<S>(),
1769 obeys_concrete_eq::<Key>(),
1770 hash_set_inv(old_m),
1771 #[trigger] hash_set_remove_ensures(old_m, final_m, k, result),
1772 ensures
1773 final_m@ == old_m@.remove(*k),
1774 result == old_m@.contains(*k),
1775{
1776 reveal(obeys_concrete_eq);
1777 broadcast use crate::set::group_set_lemmas;
1778
1779 if !result {
1780 assert(!old_m@.contains(*k));
1781 assert(old_m@.remove(*k) =~= old_m@);
1782 }
1783}
1784
1785pub broadcast proof fn lemma_hash_set_remove_ensures_if_obeys_deep_eq<
1786 Key: Eq + Hash + DeepView,
1787 S: BuildHasher,
1788 A: Allocator,
1789>(old_m: &HashSet<Key, S, A>, final_m: &HashSet<Key, S, A>, k: &Key, result: bool)
1790 requires
1791 obeys_key_model::<Key>(),
1792 builds_valid_hashers::<S>(),
1793 obeys_deep_eq::<Key>(),
1794 hash_set_inv(old_m),
1795 #[trigger] hash_set_remove_ensures(old_m, final_m, k, result),
1796 ensures
1797 final_m.deep_view() == old_m.deep_view().remove(k.deep_view()),
1798 result == old_m.deep_view().contains(k.deep_view()),
1799{
1800 reveal(obeys_deep_eq);
1801 broadcast use {crate::set::group_set_lemmas, Set::lemma_map_contains};
1802
1803 let stored_key = if result {
1804 choose|key: Key|
1805 {
1806 &&& #[trigger] old_m@.contains(key)
1807 &&& k.eq_spec(&key)
1808 &&& final_m@ == old_m@.remove(key)
1809 }
1810 } else {
1811 *k
1812 };
1813 assert(stored_key.deep_view() == k.deep_view());
1814
1815 if result {
1816 assert(old_m.deep_view().contains(k.deep_view()));
1817 } else if old_m.deep_view().contains(k.deep_view()) {
1818 let key = choose|key: Key|
1819 old_m@.contains(key) && #[trigger] key.deep_view() == k.deep_view();
1820 assert(k.eq_spec(&key));
1821 }
1822 assert forall|kd: Key::V| #[trigger]
1823 final_m.deep_view().contains(kd) <==> old_m.deep_view().remove(k.deep_view()).contains(
1824 kd,
1825 ) by {
1826 if final_m.deep_view().contains(kd) {
1827 let key = choose|key: Key| final_m@.contains(key) && #[trigger] key.deep_view() == kd;
1828 assert(old_m@.contains(key));
1829 assert(key.deep_view() != k.deep_view());
1830 }
1831 if old_m.deep_view().contains(kd) && kd != k.deep_view() {
1832 let key = choose|key: Key| old_m@.contains(key) && #[trigger] key.deep_view() == kd;
1833 assert(final_m@.contains(key));
1834 }
1835 }
1836 assert(final_m.deep_view() =~= old_m.deep_view().remove(k.deep_view()));
1837}
1838
1839pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::clear ](
1840 m: &mut HashSet<Key, S, A>,
1841)
1842 ensures
1843 final(m)@ == Set::<Key>::empty(),
1844;
1845
1846pub assume_specification<'a, Key, S, A: Allocator>[ HashSet::<Key, S, A>::iter ](
1847 m: &'a HashSet<Key, S, A>,
1848) -> (hash_keys: hash_set::Iter<'a, Key>)
1849 ensures
1850 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1851 &&& IteratorSpec::remaining(&hash_keys).unref().to_set() == m@
1852 &&& IteratorSpec::remaining(&hash_keys).no_duplicates()
1853 &&& IteratorSpec::remaining(&hash_keys).len() == m@.len()
1854 &&& into_iter_hash_keys(hash_keys) == IteratorSpec::remaining(&hash_keys).unref()
1855 &&& IteratorSpec::decrease(&hash_keys) is Some
1856 },
1857;
1858
1859pub broadcast proof fn axiom_hashset_decreases<Key, S, A: Allocator>(m: HashSet<Key, S, A>)
1860 ensures
1861 #[trigger] (decreases_to!(m => m@)),
1862{
1863 admit();
1864}
1865
1866#[verifier::reject_recursive_types_in_ground_variants(K)]
1871#[verifier::reject_recursive_types_in_ground_variants(V)]
1872#[verifier::reject_recursive_types(A)]
1873#[verifier::external_body]
1874#[verifier::external_type_specification]
1875pub struct ExOccupiedEntry<'a, K: 'a, V: 'a, A: Allocator>(OccupiedEntry<'a, K, V, A>);
1876
1877#[verifier::reject_recursive_types_in_ground_variants(K)]
1878#[verifier::accept_recursive_types(V)]
1879#[verifier::reject_recursive_types(A)]
1880#[verifier::external_body]
1881#[verifier::external_type_specification]
1882pub struct ExVacantEntry<'a, K: 'a, V: 'a, A: Allocator>(VacantEntry<'a, K, V, A>);
1883
1884#[verifier::external_type_specification]
1885#[verifier::reject_recursive_types(A)]
1886pub struct ExEntry<'a, K: 'a, V: 'a, A: Allocator>(Entry<'a, K, V, A>);
1887
1888pub trait OccupiedEntrySpecFns<K, V, A>: Sized {
1893 spec fn spec_key(self) -> K;
1894
1895 spec fn value(self) -> V;
1896
1897 #[verifier::prophetic]
1898 spec fn final_value(self) -> Option<V>;
1899}
1900
1901impl<'a, K, V, A: Allocator> OccupiedEntrySpecFns<K, V, A> for OccupiedEntry<'a, K, V, A> {
1902 uninterp spec fn spec_key(self) -> K;
1903
1904 uninterp spec fn value(self) -> V;
1905
1906 #[verifier::prophetic]
1907 uninterp spec fn final_value(self) -> Option<V>;
1908}
1909
1910pub trait VacantEntrySpecFns<K, V, A>: Sized {
1915 spec fn spec_key(self) -> K;
1916
1917 #[verifier::prophetic]
1918 spec fn final_value(self) -> Option<V>;
1919}
1920
1921impl<'a, K, V, A: Allocator> VacantEntrySpecFns<K, V, A> for VacantEntry<'a, K, V, A> {
1922 uninterp spec fn spec_key(self) -> K;
1923
1924 #[verifier::prophetic]
1925 uninterp spec fn final_value(self) -> Option<V>;
1926}
1927
1928pub trait EntrySpecFns<K, V, A>: Sized {
1932 spec fn spec_key(self) -> K;
1933
1934 spec fn value(self) -> Option<V>;
1935
1936 #[verifier::prophetic]
1937 spec fn final_value(self) -> Option<V>;
1938}
1939
1940impl<'a, K, V, A: Allocator> EntrySpecFns<K, V, A> for Entry<'a, K, V, A> {
1941 open spec fn spec_key(self) -> K {
1942 match self {
1943 Entry::Occupied(occupied_entry) => occupied_entry.spec_key(),
1944 Entry::Vacant(vacant_entry) => vacant_entry.spec_key(),
1945 }
1946 }
1947
1948 open spec fn value(self) -> Option<V> {
1949 match self {
1950 Entry::Occupied(occupied_entry) => Some(occupied_entry.value()),
1951 Entry::Vacant(vacant_entry) => None,
1952 }
1953 }
1954
1955 #[verifier::prophetic]
1956 open spec fn final_value(self) -> Option<V> {
1957 match self {
1958 Entry::Occupied(occupied_entry) => occupied_entry.final_value(),
1959 Entry::Vacant(vacant_entry) => vacant_entry.final_value(),
1960 }
1961 }
1962}
1963
1964pub broadcast axiom fn axiom_has_resolved_occupied_entry<K, V, A: Allocator>(
1965 entry: OccupiedEntry<K, V, A>,
1966)
1967 ensures
1968 #[trigger] has_resolved(entry) ==> entry.final_value() == Some(entry.value()),
1969;
1970
1971pub broadcast axiom fn axiom_has_resolved_vacant_entry<K, V, A: Allocator>(
1972 entry: VacantEntry<K, V, A>,
1973)
1974 ensures
1975 #[trigger] has_resolved(entry) ==> entry.final_value() == None::<V>,
1976;
1977
1978pub broadcast proof fn axiom_has_resolved_entry<K, V, A: Allocator>(entry: Entry<K, V, A>)
1979 ensures
1980 #[trigger] has_resolved(entry) ==> entry.final_value() == entry.value(),
1981{
1982 broadcast use axiom_has_resolved_occupied_entry;
1983 broadcast use axiom_has_resolved_vacant_entry;
1984
1985}
1986
1987#[verifier::prophetic]
1988pub open spec fn hash_map_entry_ensures<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>(
1989 old_m: &HashMap<Key, Value, S, A>,
1990 final_m: &HashMap<Key, Value, S, A>,
1991 key: Key,
1992 entry: Entry<Key, Value, A>,
1993) -> bool {
1994 ({
1995 &&& obeys_key_model::<Key>()
1996 &&& builds_valid_hashers::<S>()
1997 &&& hash_map_inv(old_m)
1998 }) ==> {
1999 &&& hash_map_inv(final_m)
2000 &&& match entry {
2001 Entry::Occupied(occupied_entry) => {
2002 &&& old_m@.contains_key(occupied_entry.spec_key())
2003 &&& key.eq_spec(&occupied_entry.spec_key())
2004 &&& occupied_entry.value() == old_m@[occupied_entry.spec_key()]
2005 },
2006 Entry::Vacant(vacant_entry) => {
2007 &&& vacant_entry.spec_key() == key
2008 &&& forall|stored_key: Key| #[trigger]
2009 old_m@.contains_key(stored_key) ==> !key.eq_spec(&stored_key)
2010 },
2011 }
2012 &&& final_m@ == match entry.final_value() {
2013 Some(value) => old_m@.insert(entry.spec_key(), value),
2014 None => old_m@.remove(entry.spec_key()),
2015 }
2016 }
2017}
2018
2019pub assume_specification<'a, Key: Hash + Eq, Value, S: BuildHasher, A: Allocator>[ HashMap::<
2020 Key,
2021 Value,
2022 S,
2023 A,
2024>::entry ](m: &'a mut HashMap<Key, Value, S, A>, key: Key) -> (entry: Entry<'a, Key, Value, A>)
2025 ensures
2026 hash_map_entry_ensures(old(m), final(m), key, entry),
2027;
2028
2029pub broadcast proof fn lemma_hash_map_entry_ensures_if_obeys_concrete_eq<
2030 Key: Eq + Hash,
2031 Value,
2032 S: BuildHasher,
2033 A: Allocator,
2034>(
2035 old_m: &HashMap<Key, Value, S, A>,
2036 final_m: &HashMap<Key, Value, S, A>,
2037 key: Key,
2038 entry: Entry<Key, Value, A>,
2039)
2040 requires
2041 obeys_key_model::<Key>(),
2042 builds_valid_hashers::<S>(),
2043 obeys_concrete_eq::<Key>(),
2044 #[trigger] hash_map_entry_ensures(old_m, final_m, key, entry),
2045 ensures
2046 entry.spec_key() == key,
2047 entry.value() == old_m@.get(key),
2048 final_m@ == match entry.final_value() {
2049 Some(value) => old_m@.insert(key, value),
2050 None => old_m@.remove(key),
2051 },
2052{
2053 reveal(obeys_concrete_eq);
2054}
2055
2056pub broadcast proof fn lemma_hash_map_entry_ensures_if_obeys_deep_eq<
2057 Key: Eq + Hash + DeepView,
2058 Value: DeepView,
2059 S: BuildHasher,
2060 A: Allocator,
2061>(
2062 old_m: &HashMap<Key, Value, S, A>,
2063 final_m: &HashMap<Key, Value, S, A>,
2064 key: Key,
2065 entry: Entry<Key, Value, A>,
2066)
2067 requires
2068 obeys_key_model::<Key>(),
2069 builds_valid_hashers::<S>(),
2070 obeys_deep_eq::<Key>(),
2071 hash_map_inv(old_m),
2072 #[trigger] hash_map_entry_ensures(old_m, final_m, key, entry),
2073 ensures
2074 entry.spec_key().deep_view() == key.deep_view(),
2075 match entry.value() {
2076 Some(value) => {
2077 &&& old_m.deep_view().contains_key(key.deep_view())
2078 &&& value.deep_view() == old_m.deep_view()[key.deep_view()]
2079 },
2080 None => !old_m.deep_view().contains_key(key.deep_view()),
2081 },
2082 final_m.deep_view() == match entry.final_value() {
2083 Some(value) => old_m.deep_view().insert(key.deep_view(), value.deep_view()),
2084 None => old_m.deep_view().remove(key.deep_view()),
2085 },
2086{
2087 reveal(obeys_deep_eq);
2088 broadcast use {
2089 crate::map::group_map_lemmas,
2090 crate::set::group_set_lemmas,
2091 Set::lemma_map_contains,
2092 };
2093
2094 reveal(hash_map_deep_view_impl);
2095
2096 let stored_key = entry.spec_key();
2097 assert(stored_key.deep_view() == key.deep_view());
2098 match entry.value() {
2099 Some(value) => {
2100 assert(old_m.deep_view().contains_key(key.deep_view()));
2101 let k = choose|k: Key|
2102 old_m@.contains_key(k) && #[trigger] k.deep_view() == key.deep_view();
2103 assert(k == stored_key);
2104 },
2105 None => {
2106 if old_m.deep_view().contains_key(key.deep_view()) {
2107 let k = choose|k: Key|
2108 old_m@.contains_key(k) && #[trigger] k.deep_view() == key.deep_view();
2109 assert(key.eq_spec(&k));
2110 }
2111 },
2112 }
2113
2114 if entry.final_value() is Some {
2115 assert(final_m@.contains_key(stored_key));
2116 }
2117 assert_maps_equal!(
2118 final_m.deep_view(),
2119 match entry.final_value() {
2120 Some(value) => old_m.deep_view().insert(key.deep_view(), value.deep_view()),
2121 None => old_m.deep_view().remove(key.deep_view()),
2122 },
2123 kd => {
2124 if final_m.deep_view().contains_key(kd) {
2125 let k = choose|k: Key|
2126 final_m@.contains_key(k) && #[trigger] k.deep_view() == kd;
2127 if entry.final_value() is None {
2128 assert(old_m@.contains_key(k));
2129 assert(k.deep_view() != key.deep_view());
2130 } else if kd != key.deep_view() {
2131 assert(old_m@.contains_key(k));
2132 }
2133 }
2134 if old_m.deep_view().contains_key(kd) && kd != key.deep_view() {
2135 let k = choose|k: Key|
2136 old_m@.contains_key(k) && #[trigger] k.deep_view() == kd;
2137 assert(final_m@.contains_key(k));
2138 }
2139 }
2140 );
2141}
2142
2143#[verifier::allow_in_spec]
2145pub assume_specification<'a, 'b, K, V, A: Allocator>[ Entry::key ](
2146 entry: &'b Entry::<'a, K, V, A>,
2147) -> (key: &'b K)
2148 returns
2149 &entry.spec_key(),
2150;
2151
2152pub assume_specification<'a, K, V, A: Allocator>[ Entry::or_insert ](
2153 entry: Entry::<'a, K, V, A>,
2154 default: V,
2155) -> (value: &'a mut V)
2156 ensures
2157 *value == (match entry.value() {
2158 Some(v) => v,
2159 None => default,
2160 }),
2161 entry.final_value() == Some(*final(value)),
2162;
2163
2164pub assume_specification<'a, K, V, A: Allocator>[ Entry::insert_entry ](
2165 entry: Entry::<'a, K, V, A>,
2166 value: V,
2167) -> (occ_entry: OccupiedEntry<'a, K, V, A>)
2168 ensures
2169 occ_entry.key() == entry.key(),
2170 occ_entry.value() == value,
2171 entry.final_value() == occ_entry.final_value(),
2172;
2173
2174mod m_occ {
2177 use super::*;
2178
2179 #[verifier::allow_in_spec]
2180 pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::key ](
2181 entry: &'b OccupiedEntry::<'a, K, V, A>,
2182 ) -> (key: &'b K)
2183 returns
2184 &entry.spec_key(),
2185 ;
2186
2187}
2188
2189pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::remove_entry ](
2190 entry: OccupiedEntry::<'a, K, V, A>,
2191) -> (kv: (K, V))
2192 ensures
2193 entry.final_value() == None,
2194 returns
2195 (*entry.key(), entry.value()),
2196;
2197
2198pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::get ](
2199 entry: &'b OccupiedEntry::<'a, K, V, A>,
2200) -> (value: &'b V)
2201 ensures
2202 *value == entry.value(),
2203;
2204
2205pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::get_mut ](
2206 entry: &'b mut OccupiedEntry::<'a, K, V, A>,
2207) -> (value: &'b mut V)
2208 ensures
2209 *value == old(entry).value(),
2210 final(entry).key() == old(entry).key(),
2211 final(entry).value() == *final(value),
2212 final(entry).final_value() == old(entry).final_value(),
2213;
2214
2215pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::into_mut ](
2216 entry: OccupiedEntry::<'a, K, V, A>,
2217) -> (value: &mut V)
2218 ensures
2219 *value == entry.value(),
2220 entry.final_value() == Some(*final(value)),
2221;
2222
2223pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::insert ](
2224 entry: &mut OccupiedEntry::<'a, K, V, A>,
2225 value: V,
2226) -> (old_value: V)
2227 ensures
2228 old_value == old(entry).value(),
2229 final(entry).key() == old(entry).key(),
2230 final(entry).value() == value,
2231 final(entry).final_value() == old(entry).final_value(),
2232;
2233
2234pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::remove ](
2235 entry: OccupiedEntry::<'a, K, V, A>,
2236) -> (value: V)
2237 ensures
2238 value == entry.value(),
2239 entry.final_value() == None,
2240;
2241
2242mod m_vac {
2245 use super::*;
2246
2247 #[verifier::allow_in_spec]
2248 pub assume_specification<'a, 'b, K: 'a, V: 'a, A: Allocator>[ VacantEntry::key ](
2249 entry: &'b VacantEntry::<'a, K, V, A>,
2250 ) -> (key: &'b K)
2251 returns
2252 &entry.spec_key(),
2253 ;
2254
2255}
2256
2257pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::into_key ](
2258 entry: VacantEntry::<'a, K, V, A>,
2259) -> (key: K)
2260 ensures
2261 key == entry.key(),
2262 entry.final_value() == None,
2263;
2264
2265pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::insert ](
2266 entry: VacantEntry::<'a, K, V, A>,
2267 value: V,
2268) -> (value_ref: &mut V)
2269 ensures
2270 *value_ref == value,
2271 entry.final_value() == Some(*final(value_ref)),
2272;
2273
2274pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::insert_entry ](
2275 entry: VacantEntry::<'a, K, V, A>,
2276 value: V,
2277) -> (occ_entry: OccupiedEntry::<'a, K, V, A>)
2278 ensures
2279 occ_entry.key() == entry.key(),
2280 occ_entry.value() == value,
2281 entry.final_value() == occ_entry.final_value(),
2282;
2283
2284pub broadcast group group_hash_axioms {
2285 lemma_hash_map_insert_ensures_if_obeys_concrete_eq,
2286 lemma_hash_map_insert_ensures_if_obeys_deep_eq,
2287 lemma_hash_map_contains_key_ensures_if_obeys_concrete_eq,
2288 lemma_hash_map_contains_key_ensures_if_obeys_deep_eq,
2289 lemma_hash_map_get_ensures_if_obeys_concrete_eq,
2290 lemma_hash_map_get_ensures_if_obeys_deep_eq,
2291 lemma_hash_map_remove_ensures_if_obeys_concrete_eq,
2292 lemma_hash_map_remove_ensures_if_obeys_deep_eq,
2293 lemma_hash_map_entry_ensures_if_obeys_concrete_eq,
2294 lemma_hash_map_entry_ensures_if_obeys_deep_eq,
2295 lemma_hash_set_insert_ensures_if_obeys_concrete_eq,
2296 lemma_hash_set_insert_ensures_if_obeys_deep_eq,
2297 lemma_hash_set_contains_ensures_if_obeys_concrete_eq,
2298 lemma_hash_set_contains_ensures_if_obeys_deep_eq,
2299 lemma_hash_set_get_ensures_if_obeys_concrete_eq,
2300 lemma_hash_set_get_ensures_if_obeys_deep_eq,
2301 lemma_hash_set_remove_ensures_if_obeys_concrete_eq,
2302 lemma_hash_set_remove_ensures_if_obeys_deep_eq,
2303 axiom_borrowed_key_hashing_matches_self,
2304 axiom_borrowed_key_hashing_matches_ref,
2305 axiom_borrowed_key_hashing_matches_box,
2306 axiom_borrowed_key_hashing_matches_string,
2307 axiom_string_obeys_hash_table_key_model,
2308 axiom_str_obeys_hash_table_key_model,
2309 axiom_bool_obeys_hash_table_key_model,
2310 axiom_u8_obeys_hash_table_key_model,
2311 axiom_u16_obeys_hash_table_key_model,
2312 axiom_u32_obeys_hash_table_key_model,
2313 axiom_u64_obeys_hash_table_key_model,
2314 axiom_u128_obeys_hash_table_key_model,
2315 axiom_usize_obeys_hash_table_key_model,
2316 axiom_i8_obeys_hash_table_key_model,
2317 axiom_i16_obeys_hash_table_key_model,
2318 axiom_i32_obeys_hash_table_key_model,
2319 axiom_i64_obeys_hash_table_key_model,
2320 axiom_i128_obeys_hash_table_key_model,
2321 axiom_isize_obeys_hash_table_key_model,
2322 axiom_box_bool_obeys_hash_table_key_model,
2323 axiom_box_integer_type_obeys_hash_table_key_model,
2324 axiom_random_state_builds_valid_hashers,
2325 axiom_spec_hash_map_len,
2326 axiom_spec_hash_set_len,
2327 axiom_hashmap_decreases,
2328 axiom_hashset_decreases,
2329 axiom_has_resolved_occupied_entry,
2330 axiom_has_resolved_vacant_entry,
2331 axiom_has_resolved_entry,
2332}
2333
2334}