1use super::super::prelude::*;
26use super::iter::IteratorSpec;
27
28use core::alloc::Allocator;
29use core::borrow::Borrow;
30use core::hash::{BuildHasher, Hash, Hasher};
31use core::marker::PhantomData;
32use core::option::Option;
33use core::option::Option::None;
34use std::collections::hash_map;
35use std::collections::hash_map::{
36 DefaultHasher, Entry, Keys, OccupiedEntry, RandomState, VacantEntry, Values,
37};
38use std::collections::hash_set;
39use std::collections::{HashMap, HashSet};
40
41verus! {
42
43#[verifier::external_type_specification]
52#[verifier::external_body]
53pub struct ExDefaultHasher(DefaultHasher);
54
55impl View for DefaultHasher {
56 type V = Seq<Seq<u8>>;
57
58 #[verifier::external_body]
59 uninterp spec fn view(&self) -> Seq<Seq<u8>>;
60}
61
62pub trait DefaultHasherAdditionalSpecFns {
63 spec fn spec_finish(s: Seq<Seq<u8>>) -> u64;
64}
65
66impl DefaultHasherAdditionalSpecFns for DefaultHasher {
67 #[verifier::external_body]
68 uninterp spec fn spec_finish(s: Seq<Seq<u8>>) -> u64;
69}
70
71pub assume_specification[ DefaultHasher::new ]() -> (result: DefaultHasher)
73 ensures
74 result@ == Seq::<Seq<u8>>::empty(),
75;
76
77pub assume_specification[ DefaultHasher::write ](state: &mut DefaultHasher, bytes: &[u8])
79 ensures
80 final(state)@ == old(state)@.push(bytes@),
81;
82
83pub assume_specification[ DefaultHasher::finish ](state: &DefaultHasher) -> (result: u64)
85 ensures
86 result == DefaultHasher::spec_finish(state@),
87;
88
89#[verifier::external_body]
107pub uninterp spec fn obeys_key_model<Key: ?Sized>() -> bool;
108
109pub broadcast proof fn axiom_bool_obeys_hash_table_key_model()
114 ensures
115 #[trigger] obeys_key_model::<bool>(),
116{
117 admit();
118}
119
120pub broadcast proof fn axiom_u8_obeys_hash_table_key_model()
121 ensures
122 #[trigger] obeys_key_model::<u8>(),
123{
124 admit();
125}
126
127pub broadcast proof fn axiom_u16_obeys_hash_table_key_model()
128 ensures
129 #[trigger] obeys_key_model::<u16>(),
130{
131 admit();
132}
133
134pub broadcast proof fn axiom_u32_obeys_hash_table_key_model()
135 ensures
136 #[trigger] obeys_key_model::<u32>(),
137{
138 admit();
139}
140
141pub broadcast proof fn axiom_u64_obeys_hash_table_key_model()
142 ensures
143 #[trigger] obeys_key_model::<u64>(),
144{
145 admit();
146}
147
148pub broadcast proof fn axiom_u128_obeys_hash_table_key_model()
149 ensures
150 #[trigger] obeys_key_model::<u128>(),
151{
152 admit();
153}
154
155pub broadcast proof fn axiom_usize_obeys_hash_table_key_model()
156 ensures
157 #[trigger] obeys_key_model::<usize>(),
158{
159 admit();
160}
161
162pub broadcast proof fn axiom_i8_obeys_hash_table_key_model()
163 ensures
164 #[trigger] obeys_key_model::<i8>(),
165{
166 admit();
167}
168
169pub broadcast proof fn axiom_i16_obeys_hash_table_key_model()
170 ensures
171 #[trigger] obeys_key_model::<i16>(),
172{
173 admit();
174}
175
176pub broadcast proof fn axiom_i32_obeys_hash_table_key_model()
177 ensures
178 #[trigger] obeys_key_model::<i32>(),
179{
180 admit();
181}
182
183pub broadcast proof fn axiom_i64_obeys_hash_table_key_model()
184 ensures
185 #[trigger] obeys_key_model::<i64>(),
186{
187 admit();
188}
189
190pub broadcast proof fn axiom_i128_obeys_hash_table_key_model()
191 ensures
192 #[trigger] obeys_key_model::<i128>(),
193{
194 admit();
195}
196
197pub broadcast proof fn axiom_isize_obeys_hash_table_key_model()
198 ensures
199 #[trigger] obeys_key_model::<isize>(),
200{
201 admit();
202}
203
204pub broadcast proof fn axiom_box_bool_obeys_hash_table_key_model()
205 ensures
206 #[trigger] obeys_key_model::<Box<bool>>(),
207{
208 admit();
209}
210
211pub broadcast proof fn axiom_box_integer_type_obeys_hash_table_key_model<Key: Integer + ?Sized>()
212 requires
213 obeys_key_model::<Key>(),
214 ensures
215 #[trigger] obeys_key_model::<Box<Key>>(),
216{
217 admit();
218}
219
220#[verifier::external_trait_specification]
221pub trait ExHasher {
222 type ExternalTraitSpecificationFor: Hasher;
223}
224
225#[verifier::external_trait_specification]
234pub trait ExBuildHasher {
235 type ExternalTraitSpecificationFor: BuildHasher;
236
237 type Hasher: Hasher;
238}
239
240#[verifier::external_body]
254pub uninterp spec fn builds_valid_hashers<T: ?Sized>() -> bool;
255
256#[verifier::external_type_specification]
263#[verifier::external_body]
264pub struct ExRandomState(RandomState);
265
266pub broadcast proof fn axiom_random_state_builds_valid_hashers()
267 ensures
268 #[trigger] builds_valid_hashers::<RandomState>(),
269{
270 admit();
271}
272
273#[verifier::external_type_specification]
276#[verifier::external_body]
277#[verifier::accept_recursive_types(Key)]
278#[verifier::accept_recursive_types(Value)]
279pub struct ExKeys<'a, Key: 'a, Value: 'a>(Keys<'a, Key, Value>);
280
281pub uninterp spec fn into_iter_keys<'a, Key, Value>(i: Keys<'a, Key, Value>) -> Seq<Key>;
284
285impl<'a, K, V> super::iter::IteratorSpecImpl for Keys<'a, K, V> {
286 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
287 true
288 }
289
290 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
291
292 uninterp spec fn will_return_none(&self) -> bool;
293
294 uninterp spec fn decrease(&self) -> Option<nat>;
295
296 open spec fn peek(&self, index: int) -> Option<Self::Item> {
297 if 0 <= index < into_iter_keys(*self).len() {
298 Some(&into_iter_keys(*self)[index])
299 } else {
300 None
301 }
302 }
303}
304
305#[verifier::external_type_specification]
308#[verifier::external_body]
309#[verifier::accept_recursive_types(Key)]
310#[verifier::accept_recursive_types(Value)]
311pub struct ExValues<'a, Key: 'a, Value: 'a>(Values<'a, Key, Value>);
312
313pub uninterp spec fn into_iter_values<'a, Key, Value>(i: Values<'a, Key, Value>) -> Seq<Value>;
316
317impl<'a, K, V> super::iter::IteratorSpecImpl for Values<'a, K, V> {
318 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
319 true
320 }
321
322 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
323
324 uninterp spec fn will_return_none(&self) -> bool;
325
326 uninterp spec fn decrease(&self) -> Option<nat>;
327
328 open spec fn peek(&self, index: int) -> Option<Self::Item> {
329 if 0 <= index < into_iter_values(*self).len() {
330 Some(&into_iter_values(*self)[index])
331 } else {
332 None
333 }
334 }
335}
336
337#[verifier::external_type_specification]
340#[verifier::external_body]
341#[verifier::accept_recursive_types(Key)]
342#[verifier::accept_recursive_types(Value)]
343pub struct ExMapIter<'a, Key: 'a, Value: 'a>(hash_map::Iter<'a, Key, Value>);
344
345pub uninterp spec fn into_iter<'a, Key, Value>(i: hash_map::Iter<'a, Key, Value>) -> Seq<
348 (Key, Value),
349>;
350
351impl<'a, K, V> super::iter::IteratorSpecImpl for hash_map::Iter<'a, K, V> {
352 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
353 true
354 }
355
356 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
357
358 uninterp spec fn will_return_none(&self) -> bool;
359
360 uninterp spec fn decrease(&self) -> Option<nat>;
361
362 open spec fn peek(&self, index: int) -> Option<Self::Item> {
363 if 0 <= index < into_iter(*self).len() {
364 let (k, v) = into_iter(*self)[index];
365 Some((&k, &v))
366 } else {
367 None
368 }
369 }
370}
371
372pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::iter ](
373 m: &'a HashMap<Key, Value, S, A>,
374) -> (iter: hash_map::Iter<'a, Key, Value>)
375 ensures
376 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
377 &&& IteratorSpec::remaining(&iter).len() == m@.dom().len()
378 &&& forall|i: int|
379 #![trigger m@.contains_key(*IteratorSpec::remaining(&iter)[i].0)]
380 #![trigger m@[*IteratorSpec::remaining(&iter)[i].0]]
381 0 <= i < IteratorSpec::remaining(&iter).len() ==> m@.contains_key(
382 *IteratorSpec::remaining(&iter)[i].0,
383 ) && m@[*IteratorSpec::remaining(&iter)[i].0] == *IteratorSpec::remaining(
384 &iter,
385 )[i].1
386 &&& forall|k: Key| #[trigger]
387 m@.contains_key(k) ==> IteratorSpec::remaining(&iter).contains((&k, &m@[k]))
388 &&& IteratorSpec::remaining(&iter).unref().to_set() == m@.kv_pairs()
389 &&& iter.remaining().no_duplicates()
390 &&& into_iter(iter) == IteratorSpec::remaining(&iter).unref()
391 &&& IteratorSpec::decrease(&iter) is Some
392 },
393;
394
395#[verifier::external_type_specification]
407#[verifier::external_body]
408#[verifier::accept_recursive_types(Key)]
409#[verifier::accept_recursive_types(Value)]
410#[verifier::reject_recursive_types(S)]
411#[verifier::reject_recursive_types(A)]
412pub struct ExHashMap<Key, Value, S, A: Allocator>(HashMap<Key, Value, S, A>);
413
414pub trait HashMapAdditionalSpecFns<Key, Value>: View<V = Map<Key, Value>> {
415 spec fn spec_index(&self, k: Key) -> Value
416 recommends
417 self@.contains_key(k),
418 ;
419}
420
421impl<Key, Value, S, A: Allocator> HashMapAdditionalSpecFns<Key, Value> for HashMap<
422 Key,
423 Value,
424 S,
425 A,
426> {
427 #[verifier::inline]
428 open spec fn spec_index(&self, k: Key) -> Value {
429 self@.index(k)
430 }
431}
432
433#[verifier::opaque]
439pub open spec fn hash_map_deep_view_impl<
440 Key: DeepView,
441 Value: DeepView,
442 S,
443 A: core::alloc::Allocator,
444>(m: HashMap<Key, Value, S, A>) -> Map<Key::V, Value::V> {
445 Map::new(
446 m@.dom().map(|k: Key| k.deep_view()),
447 |dk: Key::V|
448 {
449 let k = choose|k: Key| m@.contains_key(k) && #[trigger] k.deep_view() == dk;
450 m@[k].deep_view()
451 },
452 )
453}
454
455pub broadcast proof fn lemma_hashmap_deepview_dom<K: DeepView, V: DeepView>(m: HashMap<K, V>)
456 ensures
457 #[trigger] m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()),
458{
459 reveal(hash_map_deep_view_impl);
460 broadcast use group_hash_axioms;
461 broadcast use crate::vstd::group_vstd_default;
462
463 assert(m.deep_view().dom() =~= m@.dom().map(|k: K| k.deep_view()));
464}
465
466pub broadcast proof fn lemma_hashmap_deepview_properties<K: DeepView, V: DeepView>(m: HashMap<K, V>)
467 requires
468 crate::relations::injective(|k: K| k.deep_view()),
469 ensures
470 #![trigger m.deep_view()]
471 forall|k: K| #[trigger]
473 m@.contains_key(k) ==> m.deep_view().contains_key(k.deep_view())
474 && m.deep_view()[k.deep_view()] == m@[k].deep_view(),
475 forall|dk: <K as DeepView>::V| #[trigger]
477 m.deep_view().contains_key(dk) ==> exists|k: K|
478 k.deep_view() == dk && #[trigger] m@.contains_key(k),
479{
480 reveal(hash_map_deep_view_impl);
481 broadcast use group_hash_axioms;
482 broadcast use crate::vstd::group_vstd_default;
483
484 lemma_hashmap_deepview_dom(m);
485 assert(m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()));
486 assert forall|k: K| #[trigger] m@.contains_key(k) implies m.deep_view().contains_key(
487 k.deep_view(),
488 ) && m.deep_view()[k.deep_view()] == m@[k].deep_view() by {
489 assert(m@.dom().contains(k));
490 assert(m@.dom().map(|k: K| k.deep_view()).contains(k.deep_view()));
491 assert(m.deep_view().dom().contains(k.deep_view()));
492 let k2 = choose|k2: K| m@.contains_key(k2) && #[trigger] k2.deep_view() == k.deep_view();
493 assert forall|k1: K, k2: K| #[trigger]
494 k1.deep_view() == #[trigger] k2.deep_view() implies k1 == k2 by {
495 let ghost k_deepview = |k: K| k.deep_view();
496 assert(crate::relations::injective(k_deepview));
497 assert(k_deepview(k1) == k_deepview(k2));
498 }
499 assert(k2 == k);
500 }
501 assert forall|dk: K::V| #[trigger] m.deep_view().contains_key(dk) implies exists|k: K|
502 k.deep_view() == dk && #[trigger] m@.contains_key(k) by {
503 assert(m.deep_view().dom().contains(dk));
504 assert(m@.dom().map(|k: K| k.deep_view()).contains(dk));
505 let k = choose|k: K| #[trigger] m@.dom().contains(k) && k.deep_view() == dk;
506 assert(m@.contains_key(k));
507 }
508}
509
510pub broadcast proof fn lemma_hashmap_deepview_values<K: DeepView, V: DeepView>(m: HashMap<K, V>)
511 requires
512 crate::relations::injective(|k: K| k.deep_view()),
513 ensures
514 #[trigger] m.deep_view().values() =~= m@.values().map(|v: V| v.deep_view()),
515{
516 reveal(hash_map_deep_view_impl);
517 broadcast use group_hash_axioms;
518 broadcast use lemma_hashmap_deepview_properties;
519 broadcast use crate::vstd::group_vstd_default;
520
521 let lhs = m.deep_view().values();
522 let rhs = m@.values().map(|v: V| v.deep_view());
523 assert forall|v: V::V| #[trigger] lhs.contains(v) implies rhs.contains(v) by {
524 let dk = choose|dk: K::V| #[trigger]
525 m.deep_view().contains_key(dk) && m.deep_view()[dk] == v;
526 let k = choose|k: K| #[trigger] m@.contains_key(k) && k.deep_view() == dk;
527 let ov = choose|ov: V| #[trigger] m@.contains_key(k) && m@[k] == ov && ov.deep_view() == v;
528 assert(v == ov.deep_view());
529 assert(m@.values().contains(ov));
530 }
531}
532
533pub broadcast proof fn axiom_hashmap_deepview_borrow<
536 K: DeepView + Borrow<Q>,
537 V: DeepView,
538 Q: View<V = <K as DeepView>::V> + Hash + Eq + ?Sized,
539>(m: HashMap<K, V>, k: &Q)
540 requires
541 obeys_key_model::<K>(),
542 crate::relations::injective(|k: K| k.deep_view()),
543 ensures
544 #[trigger] contains_borrowed_key(m@, k) <==> m.deep_view().contains_key(k@),
545{
546 admit();
547}
548
549pub uninterp spec fn spec_hash_map_len<Key, Value, S, A: Allocator>(
550 m: &HashMap<Key, Value, S, A>,
551) -> usize;
552
553pub broadcast proof fn axiom_spec_hash_map_len<Key, Value, S, A: Allocator>(
554 m: &HashMap<Key, Value, S, A>,
555)
556 ensures
557 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> #[trigger] spec_hash_map_len(m)
558 == m@.len(),
559{
560 admit();
561}
562
563#[verifier::when_used_as_spec(spec_hash_map_len)]
564pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::len ](
565 m: &HashMap<Key, Value, S, A>,
566) -> (len: usize)
567 ensures
568 len == spec_hash_map_len(m),
569;
570
571pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::is_empty ](
572 m: &HashMap<Key, Value, S, A>,
573) -> (res: bool)
574 ensures
575 res == m@.is_empty(),
576;
577
578pub assume_specification<K: Clone, V: Clone, S: Clone, A: Allocator + Clone>[ <HashMap::<
579 K,
580 V,
581 S,
582 A,
583> as Clone>::clone ](this: &HashMap<K, V, S, A>) -> (other: HashMap<K, V, S, A>)
584 ensures
585 other@.dom() == this@.dom(),
586 forall|key|
587 #![trigger other@.dom().contains(key)]
588 other@.dom().contains(key) ==> cloned(this@[key], #[trigger] other@[key]),
589;
590
591pub assume_specification<Key, Value>[ HashMap::<Key, Value>::new ]() -> (m: HashMap<
592 Key,
593 Value,
594 RandomState,
595>)
596 ensures
597 m@ == Map::<Key, Value>::empty(),
598;
599
600pub assume_specification<K, V, S: core::default::Default>[ <HashMap<
601 K,
602 V,
603 S,
604> as core::default::Default>::default ]() -> (m: HashMap<K, V, S>)
605 ensures
606 m@ == Map::<K, V>::empty(),
607;
608
609pub assume_specification<Key, Value>[ HashMap::<Key, Value>::with_capacity ](capacity: usize) -> (m:
610 HashMap<Key, Value, RandomState>)
611 ensures
612 m@ == Map::<Key, Value>::empty(),
613;
614
615pub assume_specification<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>[ HashMap::<
616 Key,
617 Value,
618 S,
619 A,
620>::reserve ](m: &mut HashMap<Key, Value, S, A>, additional: usize)
621 ensures
622 final(m)@ == old(m)@,
623;
624
625pub assume_specification<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>[ HashMap::<
626 Key,
627 Value,
628 S,
629 A,
630>::insert ](m: &mut HashMap<Key, Value, S, A>, k: Key, v: Value) -> (result: Option<Value>)
631 ensures
632 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
633 &&& final(m)@ == old(m)@.insert(k, v)
634 &&& match result {
635 Some(v) => old(m)@.contains_key(k) && v == old(m)[k],
636 None => !old(m)@.contains_key(k),
637 }
638 },
639;
640
641pub uninterp spec fn contains_borrowed_key<Key, Value, Q: ?Sized>(
656 m: Map<Key, Value>,
657 k: &Q,
658) -> bool;
659
660pub broadcast proof fn axiom_contains_deref_key<Q, Value>(m: Map<Q, Value>, k: &Q)
661 ensures
662 #[trigger] contains_borrowed_key::<Q, Value, Q>(m, k) <==> m.contains_key(*k),
663{
664 admit();
665}
666
667pub broadcast proof fn axiom_contains_box<Q, Value>(m: Map<Box<Q>, Value>, k: &Q)
668 ensures
669 #[trigger] contains_borrowed_key::<Box<Q>, Value, Q>(m, k) <==> m.contains_key(
670 Box::new(*k),
671 ),
672{
673 admit();
674}
675
676pub assume_specification<
677 Key: Borrow<Q> + Hash + Eq,
678 Value,
679 S: BuildHasher,
680 A: Allocator,
681 Q: Hash + Eq + ?Sized,
682>[ HashMap::<Key, Value, S, A>::contains_key::<Q> ](
683 m: &HashMap<Key, Value, S, A>,
684 k: &Q,
685) -> (result: bool)
686 ensures
687 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> result == contains_borrowed_key(
688 m@,
689 k,
690 ),
691;
692
693pub uninterp spec fn maps_borrowed_key_to_value<Key, Value, Q: ?Sized>(
710 m: Map<Key, Value>,
711 k: &Q,
712 v: Value,
713) -> bool;
714
715pub broadcast proof fn axiom_maps_deref_key_to_value<Q, Value>(m: Map<Q, Value>, k: &Q, v: Value)
716 ensures
717 #[trigger] maps_borrowed_key_to_value::<Q, Value, Q>(m, k, v) <==> m.contains_key(*k)
718 && m[*k] == v,
719{
720 admit();
721}
722
723pub broadcast proof fn axiom_maps_box_key_to_value<Q, Value>(m: Map<Box<Q>, Value>, q: &Q, v: Value)
724 ensures
725 #[trigger] maps_borrowed_key_to_value::<Box<Q>, Value, Q>(m, q, v) <==> {
726 let k = Box::new(*q);
727 &&& m.contains_key(k)
728 &&& m[k] == v
729 },
730{
731 admit();
732}
733
734pub assume_specification<
735 'a,
736 Key: Borrow<Q> + Hash + Eq,
737 Value,
738 S: BuildHasher,
739 A: Allocator,
740 Q: Hash + Eq + ?Sized,
741>[ HashMap::<Key, Value, S, A>::get::<Q> ](m: &'a HashMap<Key, Value, S, A>, k: &Q) -> (result:
742 Option<&'a Value>)
743 ensures
744 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> match result {
745 Some(v) => maps_borrowed_key_to_value(m@, k, *v),
746 None => !contains_borrowed_key(m@, k),
747 },
748;
749
750pub uninterp spec fn borrowed_key_removed<Key, Value, Q: ?Sized>(
766 old_m: Map<Key, Value>,
767 new_m: Map<Key, Value>,
768 k: &Q,
769) -> bool;
770
771pub broadcast proof fn axiom_deref_key_removed<Q, Value>(
772 old_m: Map<Q, Value>,
773 new_m: Map<Q, Value>,
774 k: &Q,
775)
776 ensures
777 #[trigger] borrowed_key_removed::<Q, Value, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
778 *k,
779 ),
780{
781 admit();
782}
783
784pub broadcast proof fn axiom_box_key_removed<Q, Value>(
785 old_m: Map<Box<Q>, Value>,
786 new_m: Map<Box<Q>, Value>,
787 q: &Q,
788)
789 ensures
790 #[trigger] borrowed_key_removed::<Box<Q>, Value, Q>(old_m, new_m, q) <==> new_m
791 == old_m.remove(Box::new(*q)),
792{
793 admit();
794}
795
796pub assume_specification<
797 Key: Borrow<Q> + Hash + Eq,
798 Value,
799 S: BuildHasher,
800 A: Allocator,
801 Q: Hash + Eq + ?Sized,
802>[ HashMap::<Key, Value, S, A>::remove::<Q> ](m: &mut HashMap<Key, Value, S, A>, k: &Q) -> (result:
803 Option<Value>)
804 ensures
805 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
806 &&& borrowed_key_removed(old(m)@, final(m)@, k)
807 &&& match result {
808 Some(v) => maps_borrowed_key_to_value(old(m)@, k, v),
809 None => !contains_borrowed_key(old(m)@, k),
810 }
811 },
812;
813
814pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::clear ](
815 m: &mut HashMap<Key, Value, S, A>,
816)
817 ensures
818 final(m)@ == Map::<Key, Value>::empty(),
819;
820
821pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::keys ](
822 m: &'a HashMap<Key, Value, S, A>,
823) -> (keys: Keys<'a, Key, Value>)
824 ensures
825 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
826 &&& IteratorSpec::remaining(&keys).unref().to_set() == m@.dom()
827 &&& IteratorSpec::remaining(&keys).no_duplicates()
828 &&& IteratorSpec::remaining(&keys).len() == m@.dom().len()
829 &&& into_iter_keys(keys) == IteratorSpec::remaining(&keys).unref()
830 &&& IteratorSpec::decrease(&keys) is Some
831 },
832;
833
834pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::values ](
835 m: &'a HashMap<Key, Value, S, A>,
836) -> (values: Values<'a, Key, Value>)
837 ensures
838 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
839 &&& IteratorSpec::remaining(&values).unref().to_set() == m@.values()
840 &&& IteratorSpec::remaining(&values).len() == m@.dom().len()
841 &&& into_iter_values(values) == IteratorSpec::remaining(&values).unref()
842 &&& IteratorSpec::decrease(&values) is Some
843 },
844;
845
846pub broadcast proof fn axiom_hashmap_decreases<Key, Value, S>(m: HashMap<Key, Value, S>)
847 ensures
848 #[trigger] (decreases_to!(m => m@)),
849{
850 admit();
851}
852
853#[verifier::external_type_specification]
856#[verifier::external_body]
857#[verifier::accept_recursive_types(Key)]
858pub struct ExSetIter<'a, Key: 'a>(hash_set::Iter<'a, Key>);
859
860pub uninterp spec fn into_iter_hash_keys<'a, Key>(i: hash_set::Iter::<'a, Key>) -> Seq<Key>;
863
864impl<'a, K> super::iter::IteratorSpecImpl for hash_set::Iter::<'a, K> {
865 open spec fn obeys_prophetic_iter_laws(&self) -> bool {
866 true
867 }
868
869 uninterp spec fn remaining(&self) -> Seq<Self::Item>;
870
871 uninterp spec fn will_return_none(&self) -> bool;
872
873 uninterp spec fn decrease(&self) -> Option<nat>;
874
875 open spec fn peek(&self, index: int) -> Option<Self::Item> {
876 if 0 <= index < into_iter_hash_keys(*self).len() {
877 Some(&into_iter_hash_keys(*self)[index])
878 } else {
879 None
880 }
881 }
882}
883
884#[verifier::external_type_specification]
896#[verifier::external_body]
897#[verifier::accept_recursive_types(Key)]
898#[verifier::reject_recursive_types(S)]
899#[verifier::reject_recursive_types(A)]
900pub struct ExHashSet<Key, S, A: Allocator>(HashSet<Key, S, A>);
901
902pub uninterp spec fn spec_hash_set_len<Key, S, A: Allocator>(m: &HashSet<Key, S, A>) -> usize;
903
904pub broadcast proof fn axiom_spec_hash_set_len<Key, S, A: Allocator>(m: &HashSet<Key, S, A>)
905 ensures
906 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> #[trigger] spec_hash_set_len(m)
907 == m@.len(),
908{
909 admit();
910}
911
912#[verifier::when_used_as_spec(spec_hash_set_len)]
913pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::len ](
914 m: &HashSet<Key, S, A>,
915) -> (len: usize)
916 ensures
917 len == spec_hash_set_len(m),
918;
919
920pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::is_empty ](
921 m: &HashSet<Key, S, A>,
922) -> (res: bool)
923 ensures
924 res == m@.is_empty(),
925;
926
927pub assume_specification<Key>[ HashSet::<Key>::new ]() -> (m: HashSet<Key, RandomState>)
928 ensures
929 m@ == Set::<Key>::empty(),
930;
931
932pub assume_specification<T, S: core::default::Default>[ <HashSet<
933 T,
934 S,
935> as core::default::Default>::default ]() -> (m: HashSet<T, S>)
936 ensures
937 m@ == Set::<T>::empty(),
938;
939
940pub assume_specification<Key>[ HashSet::<Key>::with_capacity ](capacity: usize) -> (m: HashSet<
941 Key,
942 RandomState,
943>)
944 ensures
945 m@ == Set::<Key>::empty(),
946;
947
948pub assume_specification<Key: Eq + Hash, S: BuildHasher, A: Allocator>[ HashSet::<
949 Key,
950 S,
951 A,
952>::reserve ](m: &mut HashSet<Key, S, A>, additional: usize)
953 ensures
954 final(m)@ == old(m)@,
955;
956
957pub assume_specification<Key: Eq + Hash, S: BuildHasher, A: Allocator>[ HashSet::<
958 Key,
959 S,
960 A,
961>::insert ](m: &mut HashSet<Key, S, A>, k: Key) -> (result: bool)
962 ensures
963 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
964 &&& final(m)@ == old(m)@.insert(k)
965 &&& result == !old(m)@.contains(k)
966 },
967;
968
969pub uninterp spec fn set_contains_borrowed_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q) -> bool;
984
985pub broadcast proof fn axiom_set_contains_deref_key<Q>(m: Set<Q>, k: &Q)
986 ensures
987 #[trigger] set_contains_borrowed_key::<Q, Q>(m, k) <==> m.contains(*k),
988{
989 admit();
990}
991
992pub broadcast proof fn axiom_set_contains_box<Q>(m: Set<Box<Q>>, k: &Q)
993 ensures
994 #[trigger] set_contains_borrowed_key::<Box<Q>, Q>(m, k) <==> m.contains(Box::new(*k)),
995{
996 admit();
997}
998
999pub assume_specification<
1000 Key: Borrow<Q> + Hash + Eq,
1001 S: BuildHasher,
1002 A: Allocator,
1003 Q: Hash + Eq + ?Sized,
1004>[ HashSet::<Key, S, A>::contains ](m: &HashSet<Key, S, A>, k: &Q) -> (result: bool)
1005 ensures
1006 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> result
1007 == set_contains_borrowed_key(m@, k),
1008;
1009
1010pub uninterp spec fn sets_borrowed_key_to_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q, v: &Key) -> bool;
1027
1028pub broadcast proof fn axiom_set_deref_key_to_value<Q>(m: Set<Q>, k: &Q, v: &Q)
1029 ensures
1030 #[trigger] sets_borrowed_key_to_key::<Q, Q>(m, k, v) <==> m.contains(*k) && k == v,
1031{
1032 admit();
1033}
1034
1035pub broadcast proof fn axiom_set_box_key_to_value<Q>(m: Set<Box<Q>>, q: &Q, v: &Box<Q>)
1036 ensures
1037 #[trigger] sets_borrowed_key_to_key::<Box<Q>, Q>(m, q, v) <==> (m.contains(*v) && Box::new(
1038 *q,
1039 ) == v),
1040{
1041 admit();
1042}
1043
1044pub assume_specification<
1045 'a,
1046 Key: Borrow<Q> + Hash + Eq,
1047 S: BuildHasher,
1048 A: Allocator,
1049 Q: Hash + Eq + ?Sized,
1050>[ HashSet::<Key, S, A>::get::<Q> ](m: &'a HashSet<Key, S, A>, k: &Q) -> (result: Option<&'a Key>)
1051 ensures
1052 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> match result {
1053 Some(v) => sets_borrowed_key_to_key(m@, k, v),
1054 None => !set_contains_borrowed_key(m@, k),
1055 },
1056;
1057
1058pub uninterp spec fn sets_differ_by_borrowed_key<Key, Q: ?Sized>(
1073 old_m: Set<Key>,
1074 new_m: Set<Key>,
1075 k: &Q,
1076) -> bool;
1077
1078pub broadcast proof fn axiom_set_deref_key_removed<Q>(old_m: Set<Q>, new_m: Set<Q>, k: &Q)
1079 ensures
1080 #[trigger] sets_differ_by_borrowed_key::<Q, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
1081 *k,
1082 ),
1083{
1084 admit();
1085}
1086
1087pub broadcast proof fn axiom_set_box_key_removed<Q>(old_m: Set<Box<Q>>, new_m: Set<Box<Q>>, q: &Q)
1088 ensures
1089 #[trigger] sets_differ_by_borrowed_key::<Box<Q>, Q>(old_m, new_m, q) <==> new_m
1090 == old_m.remove(Box::new(*q)),
1091{
1092 admit();
1093}
1094
1095pub assume_specification<
1096 Key: Borrow<Q> + Hash + Eq,
1097 S: BuildHasher,
1098 A: Allocator,
1099 Q: Hash + Eq + ?Sized,
1100>[ HashSet::<Key, S, A>::remove::<Q> ](m: &mut HashSet<Key, S, A>, k: &Q) -> (result: bool)
1101 ensures
1102 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1103 &&& sets_differ_by_borrowed_key(old(m)@, final(m)@, k)
1104 &&& result == set_contains_borrowed_key(old(m)@, k)
1105 },
1106;
1107
1108pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::clear ](
1109 m: &mut HashSet<Key, S, A>,
1110)
1111 ensures
1112 final(m)@ == Set::<Key>::empty(),
1113;
1114
1115pub assume_specification<'a, Key, S, A: Allocator>[ HashSet::<Key, S, A>::iter ](
1116 m: &'a HashSet<Key, S, A>,
1117) -> (hash_keys: hash_set::Iter<'a, Key>)
1118 ensures
1119 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1120 &&& IteratorSpec::remaining(&hash_keys).unref().to_set() == m@
1121 &&& IteratorSpec::remaining(&hash_keys).no_duplicates()
1122 &&& IteratorSpec::remaining(&hash_keys).len() == m@.len()
1123 &&& into_iter_hash_keys(hash_keys) == IteratorSpec::remaining(&hash_keys).unref()
1124 &&& IteratorSpec::decrease(&hash_keys) is Some
1125 },
1126;
1127
1128pub broadcast proof fn axiom_hashset_decreases<Key, S, A: Allocator>(m: HashSet<Key, S, A>)
1129 ensures
1130 #[trigger] (decreases_to!(m => m@)),
1131{
1132 admit();
1133}
1134
1135#[verifier::reject_recursive_types_in_ground_variants(K)]
1140#[verifier::reject_recursive_types_in_ground_variants(V)]
1141#[verifier::reject_recursive_types(A)]
1142#[verifier::external_body]
1143#[verifier::external_type_specification]
1144pub struct ExOccupiedEntry<'a, K: 'a, V: 'a, A: Allocator>(OccupiedEntry<'a, K, V, A>);
1145
1146#[verifier::reject_recursive_types_in_ground_variants(K)]
1147#[verifier::accept_recursive_types(V)]
1148#[verifier::reject_recursive_types(A)]
1149#[verifier::external_body]
1150#[verifier::external_type_specification]
1151pub struct ExVacantEntry<'a, K: 'a, V: 'a, A: Allocator>(VacantEntry<'a, K, V, A>);
1152
1153#[verifier::external_type_specification]
1154#[verifier::reject_recursive_types(A)]
1155pub struct ExEntry<'a, K: 'a, V: 'a, A: Allocator>(Entry<'a, K, V, A>);
1156
1157pub trait OccupiedEntrySpecFns<K, V, A>: Sized {
1162 spec fn spec_key(self) -> K;
1163
1164 spec fn value(self) -> V;
1165
1166 #[verifier::prophetic]
1167 spec fn final_value(self) -> Option<V>;
1168}
1169
1170impl<'a, K, V, A: Allocator> OccupiedEntrySpecFns<K, V, A> for OccupiedEntry<'a, K, V, A> {
1171 uninterp spec fn spec_key(self) -> K;
1172
1173 uninterp spec fn value(self) -> V;
1174
1175 #[verifier::prophetic]
1176 uninterp spec fn final_value(self) -> Option<V>;
1177}
1178
1179pub trait VacantEntrySpecFns<K, V, A>: Sized {
1184 spec fn spec_key(self) -> K;
1185
1186 #[verifier::prophetic]
1187 spec fn final_value(self) -> Option<V>;
1188}
1189
1190impl<'a, K, V, A: Allocator> VacantEntrySpecFns<K, V, A> for VacantEntry<'a, K, V, A> {
1191 uninterp spec fn spec_key(self) -> K;
1192
1193 #[verifier::prophetic]
1194 uninterp spec fn final_value(self) -> Option<V>;
1195}
1196
1197pub trait EntrySpecFns<K, V, A>: Sized {
1201 spec fn spec_key(self) -> K;
1202
1203 spec fn value(self) -> Option<V>;
1204
1205 #[verifier::prophetic]
1206 spec fn final_value(self) -> Option<V>;
1207}
1208
1209impl<'a, K, V, A: Allocator> EntrySpecFns<K, V, A> for Entry<'a, K, V, A> {
1210 open spec fn spec_key(self) -> K {
1211 match self {
1212 Entry::Occupied(occupied_entry) => occupied_entry.spec_key(),
1213 Entry::Vacant(vacant_entry) => vacant_entry.spec_key(),
1214 }
1215 }
1216
1217 open spec fn value(self) -> Option<V> {
1218 match self {
1219 Entry::Occupied(occupied_entry) => Some(occupied_entry.value()),
1220 Entry::Vacant(vacant_entry) => None,
1221 }
1222 }
1223
1224 #[verifier::prophetic]
1225 open spec fn final_value(self) -> Option<V> {
1226 match self {
1227 Entry::Occupied(occupied_entry) => occupied_entry.final_value(),
1228 Entry::Vacant(vacant_entry) => vacant_entry.final_value(),
1229 }
1230 }
1231}
1232
1233pub broadcast axiom fn axiom_has_resolved_occupied_entry<K, V, A: Allocator>(
1234 entry: OccupiedEntry<K, V, A>,
1235)
1236 ensures
1237 #[trigger] has_resolved(entry) ==> entry.final_value() == Some(entry.value()),
1238;
1239
1240pub broadcast axiom fn axiom_has_resolved_vacant_entry<K, V, A: Allocator>(
1241 entry: VacantEntry<K, V, A>,
1242)
1243 ensures
1244 #[trigger] has_resolved(entry) ==> entry.final_value() == None::<V>,
1245;
1246
1247pub broadcast proof fn axiom_has_resolved_entry<K, V, A: Allocator>(entry: Entry<K, V, A>)
1248 ensures
1249 #[trigger] has_resolved(entry) ==> entry.final_value() == entry.value(),
1250{
1251 broadcast use axiom_has_resolved_occupied_entry;
1252 broadcast use axiom_has_resolved_vacant_entry;
1253
1254}
1255
1256pub assume_specification<'a, Key: Hash + Eq, Value, S: BuildHasher, A: Allocator>[ HashMap::<
1257 Key,
1258 Value,
1259 S,
1260 A,
1261>::entry ](m: &'a mut HashMap<Key, Value, S, A>, key: Key) -> (entry: Entry<'a, Key, Value, A>)
1262 ensures
1263 obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> (entry.key() == key
1264 && entry.value() == old(m)@.get(key) && final(m)@ == (match entry.final_value() {
1265 Some(value) => old(m)@.insert(key, value),
1266 None => old(m)@.remove(key),
1267 })),
1268;
1269
1270#[verifier::allow_in_spec]
1272pub assume_specification<'a, 'b, K, V, A: Allocator>[ Entry::key ](
1273 entry: &'b Entry::<'a, K, V, A>,
1274) -> (key: &'b K)
1275 returns
1276 &entry.spec_key(),
1277;
1278
1279pub assume_specification<'a, K, V, A: Allocator>[ Entry::or_insert ](
1280 entry: Entry::<'a, K, V, A>,
1281 default: V,
1282) -> (value: &'a mut V)
1283 ensures
1284 *value == (match entry.value() {
1285 Some(v) => v,
1286 None => default,
1287 }),
1288 entry.final_value() == Some(*final(value)),
1289;
1290
1291pub assume_specification<'a, K, V, A: Allocator>[ Entry::insert_entry ](
1292 entry: Entry::<'a, K, V, A>,
1293 value: V,
1294) -> (occ_entry: OccupiedEntry<'a, K, V, A>)
1295 ensures
1296 occ_entry.key() == entry.key(),
1297 occ_entry.value() == value,
1298 entry.final_value() == occ_entry.final_value(),
1299;
1300
1301mod m_occ {
1304 use super::*;
1305
1306 #[verifier::allow_in_spec]
1307 pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::key ](
1308 entry: &'b OccupiedEntry::<'a, K, V, A>,
1309 ) -> (key: &'b K)
1310 returns
1311 &entry.spec_key(),
1312 ;
1313
1314}
1315
1316pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::remove_entry ](
1317 entry: OccupiedEntry::<'a, K, V, A>,
1318) -> (kv: (K, V))
1319 ensures
1320 entry.final_value() == None,
1321 returns
1322 (*entry.key(), entry.value()),
1323;
1324
1325pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::get ](
1326 entry: &'b OccupiedEntry::<'a, K, V, A>,
1327) -> (value: &'b V)
1328 ensures
1329 *value == entry.value(),
1330;
1331
1332pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::get_mut ](
1333 entry: &'b mut OccupiedEntry::<'a, K, V, A>,
1334) -> (value: &'b mut V)
1335 ensures
1336 *value == old(entry).value(),
1337 final(entry).key() == old(entry).key(),
1338 final(entry).value() == *final(value),
1339 final(entry).final_value() == old(entry).final_value(),
1340;
1341
1342pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::into_mut ](
1343 entry: OccupiedEntry::<'a, K, V, A>,
1344) -> (value: &mut V)
1345 ensures
1346 *value == entry.value(),
1347 entry.final_value() == Some(*final(value)),
1348;
1349
1350pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::insert ](
1351 entry: &mut OccupiedEntry::<'a, K, V, A>,
1352 value: V,
1353) -> (old_value: V)
1354 ensures
1355 old_value == old(entry).value(),
1356 final(entry).key() == old(entry).key(),
1357 final(entry).value() == value,
1358 final(entry).final_value() == old(entry).final_value(),
1359;
1360
1361pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::remove ](
1362 entry: OccupiedEntry::<'a, K, V, A>,
1363) -> (value: V)
1364 ensures
1365 value == entry.value(),
1366 entry.final_value() == None,
1367;
1368
1369mod m_vac {
1372 use super::*;
1373
1374 #[verifier::allow_in_spec]
1375 pub assume_specification<'a, 'b, K: 'a, V: 'a, A: Allocator>[ VacantEntry::key ](
1376 entry: &'b VacantEntry::<'a, K, V, A>,
1377 ) -> (key: &'b K)
1378 returns
1379 &entry.spec_key(),
1380 ;
1381
1382}
1383
1384pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::into_key ](
1385 entry: VacantEntry::<'a, K, V, A>,
1386) -> (key: K)
1387 ensures
1388 key == entry.key(),
1389 entry.final_value() == None,
1390;
1391
1392pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::insert ](
1393 entry: VacantEntry::<'a, K, V, A>,
1394 value: V,
1395) -> (value_ref: &mut V)
1396 ensures
1397 *value_ref == value,
1398 entry.final_value() == Some(*final(value_ref)),
1399;
1400
1401pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::insert_entry ](
1402 entry: VacantEntry::<'a, K, V, A>,
1403 value: V,
1404) -> (occ_entry: OccupiedEntry::<'a, K, V, A>)
1405 ensures
1406 occ_entry.key() == entry.key(),
1407 occ_entry.value() == value,
1408 entry.final_value() == occ_entry.final_value(),
1409;
1410
1411pub broadcast group group_hash_axioms {
1412 axiom_box_key_removed,
1413 axiom_contains_deref_key,
1414 axiom_contains_box,
1415 axiom_deref_key_removed,
1416 axiom_maps_deref_key_to_value,
1417 axiom_maps_box_key_to_value,
1418 axiom_hashmap_deepview_borrow,
1419 axiom_bool_obeys_hash_table_key_model,
1420 axiom_u8_obeys_hash_table_key_model,
1421 axiom_u16_obeys_hash_table_key_model,
1422 axiom_u32_obeys_hash_table_key_model,
1423 axiom_u64_obeys_hash_table_key_model,
1424 axiom_u128_obeys_hash_table_key_model,
1425 axiom_usize_obeys_hash_table_key_model,
1426 axiom_i8_obeys_hash_table_key_model,
1427 axiom_i16_obeys_hash_table_key_model,
1428 axiom_i32_obeys_hash_table_key_model,
1429 axiom_i64_obeys_hash_table_key_model,
1430 axiom_i128_obeys_hash_table_key_model,
1431 axiom_isize_obeys_hash_table_key_model,
1432 axiom_box_bool_obeys_hash_table_key_model,
1433 axiom_box_integer_type_obeys_hash_table_key_model,
1434 axiom_random_state_builds_valid_hashers,
1435 axiom_spec_hash_map_len,
1436 axiom_set_box_key_removed,
1437 axiom_set_contains_deref_key,
1438 axiom_set_contains_box,
1439 axiom_set_deref_key_removed,
1440 axiom_set_deref_key_to_value,
1441 axiom_set_box_key_to_value,
1442 axiom_spec_hash_set_len,
1443 axiom_hashmap_decreases,
1444 axiom_hashset_decreases,
1445 axiom_has_resolved_occupied_entry,
1446 axiom_has_resolved_vacant_entry,
1447 axiom_has_resolved_entry,
1448}
1449
1450}