Skip to main content

vstd/std_specs/
hash.rs

1//! This code adds specifications for the standard-library types
2//! `std::collections::HashMap` and `std::collections::HashSet`.
3//!
4//! Most of the specification only applies if you use `HashMap<Key,
5//! Value>` or `HashSet<Key>`. If you use some custom build hasher,
6//! e.g., with`HashMap<Key, Value, CustomBuildHasher>`, the
7//! specification won't specify much unless you assume
8//! [`builds_valid_hashers<CustomBuildHasher>()`].
9//!
10//! Likewise, the specification is only meaningful when `eq_spec`
11//! faithfully models executable equality; executable equality is
12//! reflexive, symmetric, and transitive; hashing is
13//! deterministic; executable-equal keys hash identically; and
14//! cloning, when supported, preserves structural identity and
15//! executable equality. We have an axiom that all primitive types and
16//! `Box`es thereof obey this model. But if you want to use some other
17//! key type `MyKey`, you need to explicitly state your assumption
18//! that it does so with
19//! `assume(vstd::std_specs::hash::obeys_key_model::<MyKey>());`. In
20//! the future, we plan to devise a way for you to prove that it does
21//! so, so that you don't have to make such an assumption.
22//!
23//! The assumed specs don't assume that executable equality matches
24//! structural equality, or that executable equality matches deep_view
25//! equality. But we provide broadcast lemmas that derive stronger
26//! properties for when either of those do match.
27//!
28//! Borrowed-key lookups also require
29//! `borrowed_key_hashing_matches::<Key, Q>()` and use the model in
30//! `BorrowSpec`. Their postconditions additionally require `Q` to obey
31//! the hashing and equality models. Compatibility is supplied for identity,
32//! reference, `Box`, and `String` borrowing.
33//!
34//! By default, the Verus standard library brings useful axioms
35//! about the behavior of `HashMap` and `HashSet` into the ambient
36//! reasoning context by broadcasting the group
37//! `vstd::std_specs::hash::group_hash_axioms`.
38use 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/// Specifications for the behavior of
61/// [`std::collections::hash_map::DefaultHasher`](https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html).
62///
63/// We model a `DefaultHasher` as having a view (i.e., an abstract
64/// state) of type `Seq<Seq<u8>>`. This reflects the sequence of write
65/// operations performed so far, where each write is modeled as having
66/// written a sequence of bytes. There's also a specification for
67/// how a view will be transformed by `finish` into a `u64`.
68#[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
88// This is the specification of behavior for `DefaultHasher::new()`.
89pub assume_specification[ DefaultHasher::new ]() -> (result: DefaultHasher)
90    ensures
91        result@ == Seq::<Seq<u8>>::empty(),
92;
93
94// This is the specification of behavior for `DefaultHasher::write(&[u8])`.
95pub assume_specification[ DefaultHasher::write ](state: &mut DefaultHasher, bytes: &[u8])
96    ensures
97        final(state)@ == old(state)@.push(bytes@),
98;
99
100// This is the specification of behavior for `DefaultHasher::finish()`.
101pub assume_specification[ DefaultHasher::finish ](state: &DefaultHasher) -> (result: u64)
102    ensures
103        result == DefaultHasher::spec_finish(state@),
104;
105
106/// Specifies whether a type `Key` conforms to our requirements to be
107/// a key in our hash table (and hash set) model.
108///
109/// These requirements are that (1)
110/// `<Key as PartialEqSpec>::obeys_eq_spec()` is true and executable
111/// equality is reflexive, symmetric, and transitive; (2) the hash
112/// function is deterministic; (3) executable-equal keys have equal
113/// hashes; and (4) if `Key` implements `Clone`, cloning produces a
114/// result structurally identical and executable-equal to its input.
115/// `Key` need not implement `Clone`. Requirement (2) isn't satisfied
116/// by having `Key` implement `Hash`, since this trait doesn't mandate
117/// determinism.
118///
119/// The standard library has axioms that all primitive types, `String`, `str`,
120/// and `Box`es of primitive types obey this model. If you want to use some other key
121/// type `MyKey`, you need to explicitly state your assumption that it
122/// does so with
123/// `assume(vstd::std_specs::hash::obeys_key_model::<MyKey>())`.
124/// In the future, we plan to devise a way for you to prove that it
125/// does so, so that you don't have to make such an assumption.
126#[verifier::external_body]
127pub uninterp spec fn obeys_key_model<Key: ?Sized>() -> bool;
128
129/// The key model supplies faithful equality and equivalence laws, including for unsized keys.
130pub 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
152/// Whether borrowing a key preserves its `Hash` and `Eq` behavior.
153///
154/// Owned keys and their borrowed forms must hash identically for any
155/// hasher and compare equal in the same circumstances. This predicate
156/// is opaque because `Hash` does not yet have a specification model.
157pub 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
192// These axioms state that any primitive type, or `Box` thereof,
193// obeys the requirements to be a key in a hash table that
194// conforms to our hash-table model.
195// (Declare each separately to enable pruning of unused primitive types.)
196pub 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// Our model for the external trait `BuildHasher` is that for any two
304// `Hasher`s it builds, if they're both given the same write sequence
305// then their states will match and they'll produce the same digest
306// when invoked with `finish()`.
307//
308// We don't expect that all types implementing the `BuildHasher` trait
309// will conform to our model, just the types T for which
310// `builds_valid_hashers::<T>()` holds.
311#[verifier::external_trait_specification]
312pub trait ExBuildHasher {
313    type ExternalTraitSpecificationFor: BuildHasher;
314
315    type Hasher: Hasher;
316}
317
318/// Specifies whether a type conforms to our requirements to be a hash builder
319/// in our hash table (and hash set) model.
320///
321/// Our model requires that for any two `Hasher`s that the `BuildHasher` builds,
322/// if they're both given the same write sequence
323/// then their states will match and they'll produce the same digest
324/// when invoked with `finish()`.
325///
326/// The standard library has an axiom that `RandomState`, the default `BuildHasher`
327/// used by `HashMap` and `HashSet`, implements this model.
328/// If you want to use some other hash builder type `MyHashBuilder`,
329/// you need to explicitly state your assumption that it does so with
330/// `assume(vstd::std_specs::hash::builds_valid_hashers::<MyHashBuilder>())`.
331#[verifier::external_body]
332pub uninterp spec fn builds_valid_hashers<T: ?Sized>() -> bool;
333
334/// Specifications for the behavior of
335/// [`std::hash::RandomState`](https://doc.rust-lang.org/std/hash/struct.RandomState.html).
336///
337/// `RandomState` is the default `BuildHasher` used by Rust's `HashMap` and `HashSet` implementations.
338/// We have an axiom that `RandomState` satisfies [`builds_valid_hashers()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.builds_valid_hashers.html)
339/// and thereby conforms to our model of how `BuildHasher` behaves.
340#[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/// Specifications for the behavior of
352/// [`std::collections::hash_map::Keys`](https://doc.rust-lang.org/std/collections/hash_map/struct.Keys.html).
353#[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
359// To allow reasoning about the "contents" of the Keys iterator, without using
360// a prophecy, we need a function that gives us the underlying sequence of the original keys.
361pub 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/// Specifications for the behavior of
387/// [`std::collections::hash_map::Values`](https://doc.rust-lang.org/std/collections/hash_map/struct.Values.html).
388#[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
394// To allow reasoning about the "contents" of the Values iterator, without using
395// a prophecy, we need a function that gives us the underlying sequence of the original values.
396pub 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// The `iter` method of a `HashMap` returns an iterator of type `hash_map::Iter`,
422// so we specify that type here.
423#[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
429// To allow reasoning about the "contents" of the Iter iterator, without using
430// a prophecy, we need a function that gives us the underlying sequence of the original map.
431pub 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/// Specifications for the behavior of [`std::collections::HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html).
529///
530/// We model a `HashMap` as having a view of type `Map<Key, Value>`, which reflects the current state of the map.
531///
532/// These specifications are only meaningful if `obeys_key_model::<Key>()` and `builds_valid_hashers::<S>()` hold.
533/// See [`obeys_key_model()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.obeys_key_model.html)
534/// for information on use with primitive types and other types,
535/// and see [`builds_valid_hashers()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.builds_valid_hashers.html)
536/// for information on use with Rust's default implementation and custom implementations.
537///
538/// Axioms about the behavior of HashMap are present in the broadcast group `vstd::std_specs::hash::group_hash_axioms`.
539#[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/// The actual definition of `HashMap::deep_view`.
567///
568/// This is a separate function since it introduces a lot of quantifiers and revealing an opaque trait
569/// method is not supported. In most cases, it's easier to use one of the lemmas below instead
570/// of revealing this function directly.
571#[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        // all elements in m.view() are present in m.deep_view()
605        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        // all elements in m.deep_view() are present in m.view()
609        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// The `iter` method of a `HashSet` returns an iterator of type `hash_set::Iter`,
1319// so we specify that type here.
1320#[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
1325// To allow reasoning about the "contents" of the HashSet iterator, without using
1326// a prophecy, we need a function that gives us the underlying sequence of the original keys.
1327pub 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/// Specifications for the behavior of [`std::collections::HashSet`](https://doc.rust-lang.org/std/collections/struct.HashSet.html).
1353///
1354/// We model a `HashSet` as having a view of type `Set<Key>`, which reflects the current state of the set.
1355///
1356/// These specifications are only meaningful if `obeys_key_model::<Key>()` and `builds_valid_hashers::<S>()` hold.
1357/// See [`obeys_key_model()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.obeys_key_model.html)
1358/// for information on use with primitive types and custom types,
1359/// and see [`builds_valid_hashers()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.builds_valid_hashers.html)
1360/// for information on use with Rust's default implementation and custom implementations.
1361///
1362/// Axioms about the behavior of HashSet are present in the broadcast group `vstd::std_specs::hash::group_hash_axioms`.
1363#[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//////// Entry API
1867// Specs for OccupiedEntry, VacantEntry, and the Entry enum
1868// OccupiedEntry and VacantEntry are both opaque;
1869// Entry is just an enum wrapper around the other 2, so we leave it transparent.
1870#[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
1888/// Specification for an [`OccupiedEntry`].
1889/// Contains the current key and value in the entry,
1890/// and prophesies the final value after this instantiation of the entry API is complete.
1891/// The final value is optional, since the user might choose to remove the entry.
1892pub 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
1910/// Specification for a [`VacantEntry`].
1911/// Contains the current key for the entry,
1912/// and prophesies the final value after this instantiation of the entry API is complete.
1913/// The final value is optional, since the user may or may not choose to insert a value.
1914pub 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
1928/// Specification for an [`Entry`].
1929/// Contains the current key for the entry,
1930/// and prophesies the final value after this instantiation of the entry API is complete.
1931pub 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//// Entry
2144#[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
2174//// OccupiedEntry
2175// This module works around a bug with `allow_in_spec` that creates duplicate spec fn names
2176mod 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
2242//// VacantEntry
2243// This module works around a bug with `allow_in_spec` that creates duplicate spec fn names
2244mod 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} // verus!