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.
8//!
9//! Likewise, the specification is only meaningful when the `Key`
10//! obeys our hash table model, i.e., (1) `Key::hash` is
11//! deterministic, (2) any two `Key`s are identical if and only if the
12//! executable `==` operator considers them equal, and (3)
13//! `Key::clone` produces a result equal to its input. We have an
14//! axiom that all primitive types and `Box`es thereof obey this
15//! model. But if you want to use some other key type `MyKey`, you
16//! need to explicitly state your assumption that it does so with
17//! `assume(vstd::std_specs::hash::obeys_key_model::<MyKey>());`. In
18//! the future, we plan to devise a way for you to prove that it does
19//! so, so that you don't have to make such an assumption.
20//!
21//! By default, the Verus standard library brings useful axioms
22//! about the behavior of `HashMap` and `HashSet` into the ambient
23//! reasoning context by broadcasting the group
24//! `vstd::std_specs::hash::group_hash_axioms`.
25use 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/// Specifications for the behavior of
44/// [`std::collections::hash_map::DefaultHasher`](https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html).
45///
46/// We model a `DefaultHasher` as having a view (i.e., an abstract
47/// state) of type `Seq<Seq<u8>>`. This reflects the sequence of write
48/// operations performed so far, where each write is modeled as having
49/// written a sequence of bytes. There's also a specification for
50/// how a view will be transformed by `finish` into a `u64`.
51#[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
71// This is the specification of behavior for `DefaultHasher::new()`.
72pub assume_specification[ DefaultHasher::new ]() -> (result: DefaultHasher)
73    ensures
74        result@ == Seq::<Seq<u8>>::empty(),
75;
76
77// This is the specification of behavior for `DefaultHasher::write(&[u8])`.
78pub assume_specification[ DefaultHasher::write ](state: &mut DefaultHasher, bytes: &[u8])
79    ensures
80        final(state)@ == old(state)@.push(bytes@),
81;
82
83// This is the specification of behavior for `DefaultHasher::finish()`.
84pub assume_specification[ DefaultHasher::finish ](state: &DefaultHasher) -> (result: u64)
85    ensures
86        result == DefaultHasher::spec_finish(state@),
87;
88
89/// Specifies whether a type `Key` conforms to our requirements to be
90/// a key in our hash table (and hash set) model.
91///
92/// The three requirements are (1) the hash function is deterministic,
93/// (2) any two keys of type `Key` are identical if and only if they
94/// are considered equal by the executable `==` operator, and (3) the
95/// executable `Key::clone` function produces a result identical to
96/// its input. Requirement (1) isn't satisfied by having `Key`
97/// implement `Hash`, since this trait doesn't mandate determinism.
98///
99/// The standard library has axioms that all primitive types and `Box`es
100/// thereof obey this model. If you want to use some other key
101/// type `MyKey`, you need to explicitly state your assumption that it
102/// does so with
103/// `assume(vstd::std_specs::hash::obeys_key_model::<MyKey>())`.
104/// In the future, we plan to devise a way for you to prove that it
105/// does so, so that you don't have to make such an assumption.
106#[verifier::external_body]
107pub uninterp spec fn obeys_key_model<Key: ?Sized>() -> bool;
108
109// These axioms state that any primitive type, or `Box` thereof,
110// obeys the requirements to be a key in a hash table that
111// conforms to our hash-table model.
112// (Declare each separately to enable pruning of unused primitive types.)
113pub 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// Our model for the external trait `BuildHasher` is that for any two
226// `Hasher`s it builds, if they're both given the same write sequence
227// then their states will match and they'll produce the same digest
228// when invoked with `finish()`.
229//
230// We don't expect that all types implementing the `BuildHasher` trait
231// will conform to our model, just the types T for which
232// `builds_valid_hashers::<T>()` holds.
233#[verifier::external_trait_specification]
234pub trait ExBuildHasher {
235    type ExternalTraitSpecificationFor: BuildHasher;
236
237    type Hasher: Hasher;
238}
239
240/// Specifies whether a type conforms to our requirements to be a hash builder
241/// in our hash table (and hash set) model.
242///
243/// Our model requires that for any two `Hasher`s that the `BuildHasher` builds,
244/// if they're both given the same write sequence
245/// then their states will match and they'll produce the same digest
246/// when invoked with `finish()`.
247///
248/// The standard library has an axiom that `RandomState`, the default `BuildHasher`
249/// used by `HashMap` and `HashSet`, implements this model.
250/// If you want to use some other hash builder type `MyHashBuilder`,
251/// you need to explicitly state your assumption that it does so with
252/// `assume(vstd::std_specs::hash::builds_valid_hashers::<MyHashBuilder>())`.
253#[verifier::external_body]
254pub uninterp spec fn builds_valid_hashers<T: ?Sized>() -> bool;
255
256/// Specifications for the behavior of
257/// [`std::hash::RandomState`](https://doc.rust-lang.org/std/hash/struct.RandomState.html).
258///
259/// `RandomState` is the default `BuildHasher` used by Rust's `HashMap` and `HashSet` implementations.
260/// 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)
261/// and thereby conforms to our model of how `BuildHasher` behaves.
262#[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/// Specifications for the behavior of
274/// [`std::collections::hash_map::Keys`](https://doc.rust-lang.org/std/collections/hash_map/struct.Keys.html).
275#[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
281// To allow reasoning about the "contents" of the Keys iterator, without using
282// a prophecy, we need a function that gives us the underlying sequence of the original keys.
283pub 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    #[verifier::prophetic]
295    open spec fn initial_value_relation(&self, init: &Self) -> bool {
296        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
297        &&& into_iter_keys(*self) == IteratorSpec::remaining(self).unref()
298    }
299
300    uninterp spec fn decrease(&self) -> Option<nat>;
301
302    open spec fn peek(&self, index: int) -> Option<Self::Item> {
303        if 0 <= index < into_iter_keys(*self).len() {
304            Some(&into_iter_keys(*self)[index])
305        } else {
306            None
307        }
308    }
309}
310
311/// Specifications for the behavior of
312/// [`std::collections::hash_map::Values`](https://doc.rust-lang.org/std/collections/hash_map/struct.Values.html).
313#[verifier::external_type_specification]
314#[verifier::external_body]
315#[verifier::accept_recursive_types(Key)]
316#[verifier::accept_recursive_types(Value)]
317pub struct ExValues<'a, Key: 'a, Value: 'a>(Values<'a, Key, Value>);
318
319// To allow reasoning about the "contents" of the Values iterator, without using
320// a prophecy, we need a function that gives us the underlying sequence of the original values.
321pub uninterp spec fn into_iter_values<'a, Key, Value>(i: Values<'a, Key, Value>) -> Seq<Value>;
322
323impl<'a, K, V> super::iter::IteratorSpecImpl for Values<'a, K, V> {
324    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
325        true
326    }
327
328    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
329
330    uninterp spec fn will_return_none(&self) -> bool;
331
332    #[verifier::prophetic]
333    open spec fn initial_value_relation(&self, init: &Self) -> bool {
334        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
335        &&& into_iter_values(*self) == IteratorSpec::remaining(self).unref()
336    }
337
338    uninterp spec fn decrease(&self) -> Option<nat>;
339
340    open spec fn peek(&self, index: int) -> Option<Self::Item> {
341        if 0 <= index < into_iter_values(*self).len() {
342            Some(&into_iter_values(*self)[index])
343        } else {
344            None
345        }
346    }
347}
348
349// The `iter` method of a `HashMap` returns an iterator of type `hash_map::Iter`,
350// so we specify that type here.
351#[verifier::external_type_specification]
352#[verifier::external_body]
353#[verifier::accept_recursive_types(Key)]
354#[verifier::accept_recursive_types(Value)]
355pub struct ExMapIter<'a, Key: 'a, Value: 'a>(hash_map::Iter<'a, Key, Value>);
356
357// To allow reasoning about the "contents" of the Iter iterator, without using
358// a prophecy, we need a function that gives us the underlying sequence of the original map.
359pub uninterp spec fn into_iter<'a, Key, Value>(i: hash_map::Iter<'a, Key, Value>) -> Seq<
360    (Key, Value),
361>;
362
363impl<'a, K, V> super::iter::IteratorSpecImpl for hash_map::Iter<'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    uninterp spec fn will_return_none(&self) -> bool;
371
372    #[verifier::prophetic]
373    open spec fn initial_value_relation(&self, init: &Self) -> bool {
374        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
375        &&& into_iter(*self) == IteratorSpec::remaining(self).unref()
376    }
377
378    uninterp spec fn decrease(&self) -> Option<nat>;
379
380    open spec fn peek(&self, index: int) -> Option<Self::Item> {
381        if 0 <= index < into_iter(*self).len() {
382            let (k, v) = into_iter(*self)[index];
383            Some((&k, &v))
384        } else {
385            None
386        }
387    }
388}
389
390// To allow reasoning about the ghost iterator when the executable
391// function `iter()` is invoked in a `for` loop header (e.g., in
392// `for x in it: v.iter() { ... }`), we need to specify the behavior of
393// the iterator in spec mode. To do that, we add
394// `#[verifier::when_used_as_spec(spec_iter)]` to the specification for
395// the executable `iter` method and define that spec function here.
396pub uninterp spec fn spec_hash_map_iter<'a, Key, Value, S, A: Allocator>(
397    m: &'a HashMap<Key, Value, S, A>,
398) -> (r: hash_map::Iter<'a, Key, Value>);
399
400pub broadcast proof fn axiom_spec_hash_map_iter<'a, Key, Value, S>(m: &'a HashMap<Key, Value, S>)
401    ensures
402        ({
403            let v = #[trigger] spec_hash_map_iter(m).remaining();
404            &&& v.len() == m@.dom().len()
405            &&& forall|i: int|
406                #![trigger m@.contains_key(*v[i].0)]
407                #![trigger m@[*v[i].0]]
408                0 <= i < v.len() ==> m@.contains_key(*v[i].0) && m@[*v[i].0] == *v[i].1
409            &&& forall|k: Key| #[trigger] m@.contains_key(k) ==> v.contains((&k, &m@[k]))
410            &&& v.unref().to_set() == m@.kv_pairs()
411        }),
412{
413    admit();
414}
415
416#[verifier::when_used_as_spec(spec_hash_map_iter)]
417pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::iter ](
418    m: &'a HashMap<Key, Value, S, A>,
419) -> (iter: hash_map::Iter<'a, Key, Value>)
420    ensures
421        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
422            &&& iter == spec_hash_map_iter(m)
423            &&& iter.remaining().no_duplicates()
424            &&& IteratorSpec::decrease(&iter) is Some
425            &&& IteratorSpec::initial_value_relation(&iter, &iter)
426        },
427;
428
429/// Specifications for the behavior of [`std::collections::HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html).
430///
431/// We model a `HashMap` as having a view of type `Map<Key, Value>`, which reflects the current state of the map.
432///
433/// These specifications are only meaningful if `obeys_key_model::<Key>()` and `builds_valid_hashers::<S>()` hold.
434/// See [`obeys_key_model()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.obeys_key_model.html)
435/// for information on use with primitive types and other types,
436/// and see [`builds_valid_hashers()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.builds_valid_hashers.html)
437/// for information on use with Rust's default implementation and custom implementations.
438///
439/// Axioms about the behavior of HashMap are present in the broadcast group `vstd::std_specs::hash::group_hash_axioms`.
440#[verifier::external_type_specification]
441#[verifier::external_body]
442#[verifier::accept_recursive_types(Key)]
443#[verifier::accept_recursive_types(Value)]
444#[verifier::reject_recursive_types(S)]
445#[verifier::reject_recursive_types(A)]
446pub struct ExHashMap<Key, Value, S, A: Allocator>(HashMap<Key, Value, S, A>);
447
448pub trait HashMapAdditionalSpecFns<Key, Value>: View<V = Map<Key, Value>> {
449    spec fn spec_index(&self, k: Key) -> Value
450        recommends
451            self@.contains_key(k),
452    ;
453}
454
455impl<Key, Value, S, A: Allocator> HashMapAdditionalSpecFns<Key, Value> for HashMap<
456    Key,
457    Value,
458    S,
459    A,
460> {
461    #[verifier::inline]
462    open spec fn spec_index(&self, k: Key) -> Value {
463        self@.index(k)
464    }
465}
466
467/// The actual definition of `HashMap::deep_view`.
468///
469/// This is a separate function since it introduces a lot of quantifiers and revealing an opaque trait
470/// method is not supported. In most cases, it's easier to use one of the lemmas below instead
471/// of revealing this function directly.
472#[verifier::opaque]
473pub open spec fn hash_map_deep_view_impl<
474    Key: DeepView,
475    Value: DeepView,
476    S,
477    A: core::alloc::Allocator,
478>(m: HashMap<Key, Value, S, A>) -> Map<Key::V, Value::V> {
479    Map::new(
480        |k: Key::V|
481            exists|orig_k: Key| #[trigger] m@.contains_key(orig_k) && k == orig_k.deep_view(),
482        |dk: Key::V|
483            {
484                let k = choose|k: Key| m@.contains_key(k) && #[trigger] k.deep_view() == dk;
485                m@[k].deep_view()
486            },
487    )
488}
489
490pub broadcast proof fn lemma_hashmap_deepview_dom<K: DeepView, V: DeepView>(m: HashMap<K, V>)
491    ensures
492        #[trigger] m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()),
493{
494    reveal(hash_map_deep_view_impl);
495    broadcast use group_hash_axioms;
496    broadcast use crate::vstd::group_vstd_default;
497
498    assert(m.deep_view().dom() =~= m@.dom().map(|k: K| k.deep_view()));
499}
500
501pub broadcast proof fn lemma_hashmap_deepview_properties<K: DeepView, V: DeepView>(m: HashMap<K, V>)
502    requires
503        crate::relations::injective(|k: K| k.deep_view()),
504    ensures
505        #![trigger m.deep_view()]
506        // all elements in m.view() are present in m.deep_view()
507        forall|k: K| #[trigger]
508            m@.contains_key(k) ==> m.deep_view().contains_key(k.deep_view())
509                && m.deep_view()[k.deep_view()] == m@[k].deep_view(),
510        // all elements in m.deep_view() are present in m.view()
511        forall|dk: <K as DeepView>::V| #[trigger]
512            m.deep_view().contains_key(dk) ==> exists|k: K|
513                k.deep_view() == dk && #[trigger] m@.contains_key(k),
514{
515    reveal(hash_map_deep_view_impl);
516    broadcast use group_hash_axioms;
517    broadcast use crate::vstd::group_vstd_default;
518
519    assert(m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()));
520    assert forall|k: K| #[trigger] m@.contains_key(k) implies m.deep_view().contains_key(
521        k.deep_view(),
522    ) && m.deep_view()[k.deep_view()] == m@[k].deep_view() by {
523        assert forall|k1: K, k2: K| #[trigger]
524            k1.deep_view() == #[trigger] k2.deep_view() implies k1 == k2 by {
525            let ghost k_deepview = |k: K| k.deep_view();
526            assert(crate::relations::injective(k_deepview));
527            assert(k_deepview(k1) == k_deepview(k2));
528        }
529    }
530}
531
532pub broadcast proof fn lemma_hashmap_deepview_values<K: DeepView, V: DeepView>(m: HashMap<K, V>)
533    requires
534        crate::relations::injective(|k: K| k.deep_view()),
535    ensures
536        #[trigger] m.deep_view().values() =~= m@.values().map(|v: V| v.deep_view()),
537{
538    reveal(hash_map_deep_view_impl);
539    broadcast use group_hash_axioms;
540    broadcast use lemma_hashmap_deepview_properties;
541    broadcast use crate::vstd::group_vstd_default;
542
543    let lhs = m.deep_view().values();
544    let rhs = m@.values().map(|v: V| v.deep_view());
545    assert forall|v: V::V| #[trigger] lhs.contains(v) implies rhs.contains(v) by {
546        let dk = choose|dk: K::V| #[trigger]
547            m.deep_view().contains_key(dk) && m.deep_view()[dk] == v;
548        let k = choose|k: K| #[trigger] m@.contains_key(k) && k.deep_view() == dk;
549        let ov = choose|ov: V| #[trigger] m@.contains_key(k) && m@[k] == ov && ov.deep_view() == v;
550        assert(v == ov.deep_view());
551        assert(m@.values().contains(ov));
552    }
553}
554
555/// Borrowing a key works the same way on deep_view as on view,
556/// if deep_view is injective; see `axiom_contains_deref_key`.
557pub broadcast proof fn axiom_hashmap_deepview_borrow<
558    K: DeepView + Borrow<Q>,
559    V: DeepView,
560    Q: View<V = <K as DeepView>::V> + Hash + Eq + ?Sized,
561>(m: HashMap<K, V>, k: &Q)
562    requires
563        obeys_key_model::<K>(),
564        crate::relations::injective(|k: K| k.deep_view()),
565    ensures
566        #[trigger] contains_borrowed_key(m@, k) <==> m.deep_view().contains_key(k@),
567{
568    admit();
569}
570
571/// A `Map` constructed from a `HashMap` is always finite.
572pub broadcast proof fn axiom_hashmap_view_finite_dom<K, V>(m: HashMap<K, V>)
573    ensures
574        #[trigger] m@.dom().finite(),
575{
576    admit();
577}
578
579pub uninterp spec fn spec_hash_map_len<Key, Value, S, A: Allocator>(
580    m: &HashMap<Key, Value, S, A>,
581) -> usize;
582
583pub broadcast proof fn axiom_spec_hash_map_len<Key, Value, S, A: Allocator>(
584    m: &HashMap<Key, Value, S, A>,
585)
586    ensures
587        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> #[trigger] spec_hash_map_len(m)
588            == m@.len(),
589{
590    admit();
591}
592
593#[verifier::when_used_as_spec(spec_hash_map_len)]
594pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::len ](
595    m: &HashMap<Key, Value, S, A>,
596) -> (len: usize)
597    ensures
598        len == spec_hash_map_len(m),
599;
600
601pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::is_empty ](
602    m: &HashMap<Key, Value, S, A>,
603) -> (res: bool)
604    ensures
605        res == m@.is_empty(),
606;
607
608pub assume_specification<K: Clone, V: Clone, S: Clone, A: Allocator + Clone>[ <HashMap::<
609    K,
610    V,
611    S,
612    A,
613> as Clone>::clone ](this: &HashMap<K, V, S, A>) -> (other: HashMap<K, V, S, A>)
614    ensures
615        other@ == this@,
616;
617
618pub assume_specification<Key, Value>[ HashMap::<Key, Value>::new ]() -> (m: HashMap<
619    Key,
620    Value,
621    RandomState,
622>)
623    ensures
624        m@ == Map::<Key, Value>::empty(),
625;
626
627pub assume_specification<K, V, S: core::default::Default>[ <HashMap<
628    K,
629    V,
630    S,
631> as core::default::Default>::default ]() -> (m: HashMap<K, V, S>)
632    ensures
633        m@ == Map::<K, V>::empty(),
634;
635
636pub assume_specification<Key, Value>[ HashMap::<Key, Value>::with_capacity ](capacity: usize) -> (m:
637    HashMap<Key, Value, RandomState>)
638    ensures
639        m@ == Map::<Key, Value>::empty(),
640;
641
642pub assume_specification<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>[ HashMap::<
643    Key,
644    Value,
645    S,
646    A,
647>::reserve ](m: &mut HashMap<Key, Value, S, A>, additional: usize)
648    ensures
649        final(m)@ == old(m)@,
650;
651
652pub assume_specification<Key: Eq + Hash, Value, S: BuildHasher, A: Allocator>[ HashMap::<
653    Key,
654    Value,
655    S,
656    A,
657>::insert ](m: &mut HashMap<Key, Value, S, A>, k: Key, v: Value) -> (result: Option<Value>)
658    ensures
659        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
660            &&& final(m)@ == old(m)@.insert(k, v)
661            &&& match result {
662                Some(v) => old(m)@.contains_key(k) && v == old(m)[k],
663                None => !old(m)@.contains_key(k),
664            }
665        },
666;
667
668// The specification for `contains_key` has a parameter `key: &Q`
669// where you'd expect to find `key: &Key`. This allows for the case
670// that `Key` can be borrowed as something other than `&Key`. For
671// instance, `Box<u32>` can be borrowed as `&u32` and `String` can be
672// borrowed as `&str`, so in those cases `Q` would be `u32` and `str`
673// respectively.
674// To deal with this, we have a specification function that opaquely
675// specifies what it means for a map to contain a borrowed key of type
676// `&Q`. And the postcondition of `contains_key` just says that its
677// result matches the output of that specification function. But this
678// isn't very helpful by itself, since there's no body to that
679// specification function. So we have special-case axioms that say
680// what this means in two important circumstances: (1) `Key = Q` and
681// (2) `Key = Box<Q>`.
682pub uninterp spec fn contains_borrowed_key<Key, Value, Q: ?Sized>(
683    m: Map<Key, Value>,
684    k: &Q,
685) -> bool;
686
687pub broadcast proof fn axiom_contains_deref_key<Q, Value>(m: Map<Q, Value>, k: &Q)
688    ensures
689        #[trigger] contains_borrowed_key::<Q, Value, Q>(m, k) <==> m.contains_key(*k),
690{
691    admit();
692}
693
694pub broadcast proof fn axiom_contains_box<Q, Value>(m: Map<Box<Q>, Value>, k: &Q)
695    ensures
696        #[trigger] contains_borrowed_key::<Box<Q>, Value, Q>(m, k) <==> m.contains_key(
697            Box::new(*k),
698        ),
699{
700    admit();
701}
702
703pub assume_specification<
704    Key: Borrow<Q> + Hash + Eq,
705    Value,
706    S: BuildHasher,
707    A: Allocator,
708    Q: Hash + Eq + ?Sized,
709>[ HashMap::<Key, Value, S, A>::contains_key::<Q> ](
710    m: &HashMap<Key, Value, S, A>,
711    k: &Q,
712) -> (result: bool)
713    ensures
714        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> result == contains_borrowed_key(
715            m@,
716            k,
717        ),
718;
719
720// The specification for `get` has a parameter `key: &Q` where you'd
721// expect to find `key: &Key`. This allows for the case that `Key` can
722// be borrowed as something other than `&Key`. For instance,
723// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
724// as `&str`, so in those cases `Q` would be `u32` and `str`
725// respectively.
726// To deal with this, we have a specification function that opaquely
727// specifies what it means for a map to map a borrowed key of type
728// `&Q` to a certain value. And the postcondition of `get` says that
729// its result matches the output of that specification function. (It
730// also says that its result corresponds to the output of
731// `contains_borrowed_key`, discussed above.) But this isn't very
732// helpful by itself, since there's no body to that specification
733// function. So we have special-case axioms that say what this means
734// in two important circumstances: (1) `Key = Q` and (2) `Key =
735// Box<Q>`.
736pub uninterp spec fn maps_borrowed_key_to_value<Key, Value, Q: ?Sized>(
737    m: Map<Key, Value>,
738    k: &Q,
739    v: Value,
740) -> bool;
741
742pub broadcast proof fn axiom_maps_deref_key_to_value<Q, Value>(m: Map<Q, Value>, k: &Q, v: Value)
743    ensures
744        #[trigger] maps_borrowed_key_to_value::<Q, Value, Q>(m, k, v) <==> m.contains_key(*k)
745            && m[*k] == v,
746{
747    admit();
748}
749
750pub broadcast proof fn axiom_maps_box_key_to_value<Q, Value>(m: Map<Box<Q>, Value>, q: &Q, v: Value)
751    ensures
752        #[trigger] maps_borrowed_key_to_value::<Box<Q>, Value, Q>(m, q, v) <==> {
753            let k = Box::new(*q);
754            &&& m.contains_key(k)
755            &&& m[k] == v
756        },
757{
758    admit();
759}
760
761pub assume_specification<
762    'a,
763    Key: Borrow<Q> + Hash + Eq,
764    Value,
765    S: BuildHasher,
766    A: Allocator,
767    Q: Hash + Eq + ?Sized,
768>[ HashMap::<Key, Value, S, A>::get::<Q> ](m: &'a HashMap<Key, Value, S, A>, k: &Q) -> (result:
769    Option<&'a Value>)
770    ensures
771        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> match result {
772            Some(v) => maps_borrowed_key_to_value(m@, k, *v),
773            None => !contains_borrowed_key(m@, k),
774        },
775;
776
777// The specification for `remove` has a parameter `key: &Q` where
778// you'd expect to find `key: &Key`. This allows for the case that
779// `Key` can be borrowed as something other than `&Key`. For instance,
780// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
781// as `&str`, so in those cases `Q` would be `u32` and `str`
782// respectively. To deal with this, we have a specification function
783// that opaquely specifies what it means for two maps to be related by
784// a remove of a certain `&Q`. And the postcondition of `remove` says
785// that `old(self)@` and `self@` satisfy that relationship. (It also
786// says that its result corresponds to the output of
787// `contains_borrowed_key` and `maps_borrowed_key_to_value`, discussed
788// above.) But this isn't very helpful by itself, since there's no
789// body to that specification function. So we have special-case axioms
790// that say what this means in two important circumstances: (1) `Key =
791// Q` and (2) `Key = Box<Q>`.
792pub uninterp spec fn borrowed_key_removed<Key, Value, Q: ?Sized>(
793    old_m: Map<Key, Value>,
794    new_m: Map<Key, Value>,
795    k: &Q,
796) -> bool;
797
798pub broadcast proof fn axiom_deref_key_removed<Q, Value>(
799    old_m: Map<Q, Value>,
800    new_m: Map<Q, Value>,
801    k: &Q,
802)
803    ensures
804        #[trigger] borrowed_key_removed::<Q, Value, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
805            *k,
806        ),
807{
808    admit();
809}
810
811pub broadcast proof fn axiom_box_key_removed<Q, Value>(
812    old_m: Map<Box<Q>, Value>,
813    new_m: Map<Box<Q>, Value>,
814    q: &Q,
815)
816    ensures
817        #[trigger] borrowed_key_removed::<Box<Q>, Value, Q>(old_m, new_m, q) <==> new_m
818            == old_m.remove(Box::new(*q)),
819{
820    admit();
821}
822
823pub assume_specification<
824    Key: Borrow<Q> + Hash + Eq,
825    Value,
826    S: BuildHasher,
827    A: Allocator,
828    Q: Hash + Eq + ?Sized,
829>[ HashMap::<Key, Value, S, A>::remove::<Q> ](m: &mut HashMap<Key, Value, S, A>, k: &Q) -> (result:
830    Option<Value>)
831    ensures
832        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
833            &&& borrowed_key_removed(old(m)@, final(m)@, k)
834            &&& match result {
835                Some(v) => maps_borrowed_key_to_value(old(m)@, k, v),
836                None => !contains_borrowed_key(old(m)@, k),
837            }
838        },
839;
840
841pub assume_specification<Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::clear ](
842    m: &mut HashMap<Key, Value, S, A>,
843)
844    ensures
845        final(m)@ == Map::<Key, Value>::empty(),
846;
847
848// To allow reasoning about the ghost Keys iterator when the executable
849// function `keys()` is invoked in a `for` loop header (e.g., in
850// `for x in it: m.keys() { ... }`), we need to specify the behavior of
851// the iterator in spec mode. To do that, we add
852// `#[verifier::when_used_as_spec(spec_iter)` to the specification for
853// the executable `iter` method and define that spec function here.
854pub uninterp spec fn spec_keys_iter<'a, Key, Value, S, A: Allocator>(
855    m: &'a HashMap<Key, Value, S, A>,
856) -> (keys: Keys<'a, Key, Value>);
857
858pub broadcast proof fn axiom_spec_keys_iter<'a, Key, Value, S, A: Allocator>(
859    m: &'a HashMap<Key, Value, S, A>,
860)
861    ensures
862        (#[trigger] spec_keys_iter(m).remaining()).unref().to_set() == m@.dom(),
863        spec_keys_iter(m).remaining().no_duplicates(),
864        spec_keys_iter(m).remaining().len() == m@.dom().len(),
865{
866    admit();
867}
868
869#[verifier::when_used_as_spec(spec_keys_iter)]
870pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::keys ](
871    m: &'a HashMap<Key, Value, S, A>,
872) -> (keys: Keys<'a, Key, Value>)
873    ensures
874        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
875            &&& keys == spec_keys_iter(m)
876            &&& IteratorSpec::decrease(&keys) is Some
877            &&& IteratorSpec::initial_value_relation(&keys, &keys)
878        },
879;
880
881// To allow reasoning about the ghost Values iterator when the executable
882// function `value()` is invoked in a `for` loop header (e.g., in
883// `for x in it: m.keys() { ... }`), we need to specify the behavior of
884// the iterator in spec mode. To do that, we add
885// `#[verifier::when_used_as_spec(spec_iter)` to the specification for
886// the executable `iter` method and define that spec function here.
887pub uninterp spec fn spec_values_iter<'a, Key, Value, S, A: Allocator>(
888    m: &'a HashMap<Key, Value, S, A>,
889) -> (values: Values<'a, Key, Value>);
890
891pub broadcast proof fn axiom_spec_values_iter<'a, Key, Value, S, A: Allocator>(
892    m: &'a HashMap<Key, Value, S, A>,
893)
894    ensures
895        (#[trigger] spec_values_iter(m).remaining()).unref().to_set() == m@.values(),
896        spec_values_iter(m).remaining().len() == m@.dom().len(),
897{
898    admit();
899}
900
901#[verifier::when_used_as_spec(spec_values_iter)]
902pub assume_specification<'a, Key, Value, S, A: Allocator>[ HashMap::<Key, Value, S, A>::values ](
903    m: &'a HashMap<Key, Value, S, A>,
904) -> (values: Values<'a, Key, Value>)
905    ensures
906        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
907            &&& values == spec_values_iter(m)
908            &&& IteratorSpec::decrease(&values) is Some
909            &&& IteratorSpec::initial_value_relation(&values, &values)
910        },
911;
912
913pub broadcast proof fn axiom_hashmap_decreases<Key, Value, S>(m: HashMap<Key, Value, S>)
914    ensures
915        #[trigger] (decreases_to!(m => m@)),
916{
917    admit();
918}
919
920// The `iter` method of a `HashSet` returns an iterator of type `hash_set::Iter`,
921// so we specify that type here.
922#[verifier::external_type_specification]
923#[verifier::external_body]
924#[verifier::accept_recursive_types(Key)]
925pub struct ExSetIter<'a, Key: 'a>(hash_set::Iter<'a, Key>);
926
927// To allow reasoning about the "contents" of the HashSet iterator, without using
928// a prophecy, we need a function that gives us the underlying sequence of the original keys.
929pub uninterp spec fn into_iter_hash_keys<'a, Key>(i: hash_set::Iter::<'a, Key>) -> Seq<Key>;
930
931impl<'a, K> super::iter::IteratorSpecImpl for hash_set::Iter::<'a, K> {
932    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
933        true
934    }
935
936    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
937
938    uninterp spec fn will_return_none(&self) -> bool;
939
940    #[verifier::prophetic]
941    open spec fn initial_value_relation(&self, init: &Self) -> bool {
942        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
943        &&& into_iter_hash_keys(*self) == IteratorSpec::remaining(self).unref()
944    }
945
946    uninterp spec fn decrease(&self) -> Option<nat>;
947
948    open spec fn peek(&self, index: int) -> Option<Self::Item> {
949        if 0 <= index < into_iter_hash_keys(*self).len() {
950            Some(&into_iter_hash_keys(*self)[index])
951        } else {
952            None
953        }
954    }
955}
956
957/// Specifications for the behavior of [`std::collections::HashSet`](https://doc.rust-lang.org/std/collections/struct.HashSet.html).
958///
959/// We model a `HashSet` as having a view of type `Set<Key>`, which reflects the current state of the set.
960///
961/// These specifications are only meaningful if `obeys_key_model::<Key>()` and `builds_valid_hashers::<S>()` hold.
962/// See [`obeys_key_model()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.obeys_key_model.html)
963/// for information on use with primitive types and custom types,
964/// and see [`builds_valid_hashers()`](https://verus-lang.github.io/verus/verusdoc/vstd/std_specs/hash/fn.builds_valid_hashers.html)
965/// for information on use with Rust's default implementation and custom implementations.
966///
967/// Axioms about the behavior of HashSet are present in the broadcast group `vstd::std_specs::hash::group_hash_axioms`.
968#[verifier::external_type_specification]
969#[verifier::external_body]
970#[verifier::accept_recursive_types(Key)]
971#[verifier::reject_recursive_types(S)]
972#[verifier::reject_recursive_types(A)]
973pub struct ExHashSet<Key, S, A: Allocator>(HashSet<Key, S, A>);
974
975pub uninterp spec fn spec_hash_set_len<Key, S, A: Allocator>(m: &HashSet<Key, S, A>) -> usize;
976
977pub broadcast proof fn axiom_spec_hash_set_len<Key, S, A: Allocator>(m: &HashSet<Key, S, A>)
978    ensures
979        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> #[trigger] spec_hash_set_len(m)
980            == m@.len(),
981{
982    admit();
983}
984
985#[verifier::when_used_as_spec(spec_hash_set_len)]
986pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::len ](
987    m: &HashSet<Key, S, A>,
988) -> (len: usize)
989    ensures
990        len == spec_hash_set_len(m),
991;
992
993pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::is_empty ](
994    m: &HashSet<Key, S, A>,
995) -> (res: bool)
996    ensures
997        res == m@.is_empty(),
998;
999
1000pub assume_specification<Key>[ HashSet::<Key>::new ]() -> (m: HashSet<Key, RandomState>)
1001    ensures
1002        m@ == Set::<Key>::empty(),
1003;
1004
1005pub assume_specification<T, S: core::default::Default>[ <HashSet<
1006    T,
1007    S,
1008> as core::default::Default>::default ]() -> (m: HashSet<T, S>)
1009    ensures
1010        m@ == Set::<T>::empty(),
1011;
1012
1013pub assume_specification<Key>[ HashSet::<Key>::with_capacity ](capacity: usize) -> (m: HashSet<
1014    Key,
1015    RandomState,
1016>)
1017    ensures
1018        m@ == Set::<Key>::empty(),
1019;
1020
1021pub assume_specification<Key: Eq + Hash, S: BuildHasher, A: Allocator>[ HashSet::<
1022    Key,
1023    S,
1024    A,
1025>::reserve ](m: &mut HashSet<Key, S, A>, additional: usize)
1026    ensures
1027        final(m)@ == old(m)@,
1028;
1029
1030pub assume_specification<Key: Eq + Hash, S: BuildHasher, A: Allocator>[ HashSet::<
1031    Key,
1032    S,
1033    A,
1034>::insert ](m: &mut HashSet<Key, S, A>, k: Key) -> (result: bool)
1035    ensures
1036        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1037            &&& final(m)@ == old(m)@.insert(k)
1038            &&& result == !old(m)@.contains(k)
1039        },
1040;
1041
1042// The specification for `contains` has a parameter `key: &Q`
1043// where you'd expect to find `key: &Key`. This allows for the case
1044// that `Key` can be borrowed as something other than `&Key`. For
1045// instance, `Box<u32>` can be borrowed as `&u32` and `String` can be
1046// borrowed as `&str`, so in those cases `Q` would be `u32` and `str`
1047// respectively.
1048// To deal with this, we have a specification function that opaquely
1049// specifies what it means for a set to contain a borrowed key of type
1050// `&Q`. And the postcondition of `contains` just says that its
1051// result matches the output of that specification function. But this
1052// isn't very helpful by itself, since there's no body to that
1053// specification function. So we have special-case axioms that say
1054// what this means in two important circumstances: (1) `Key = Q` and
1055// (2) `Key = Box<Q>`.
1056pub uninterp spec fn set_contains_borrowed_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q) -> bool;
1057
1058pub broadcast proof fn axiom_set_contains_deref_key<Q>(m: Set<Q>, k: &Q)
1059    ensures
1060        #[trigger] set_contains_borrowed_key::<Q, Q>(m, k) <==> m.contains(*k),
1061{
1062    admit();
1063}
1064
1065pub broadcast proof fn axiom_set_contains_box<Q>(m: Set<Box<Q>>, k: &Q)
1066    ensures
1067        #[trigger] set_contains_borrowed_key::<Box<Q>, Q>(m, k) <==> m.contains(Box::new(*k)),
1068{
1069    admit();
1070}
1071
1072pub assume_specification<
1073    Key: Borrow<Q> + Hash + Eq,
1074    S: BuildHasher,
1075    A: Allocator,
1076    Q: Hash + Eq + ?Sized,
1077>[ HashSet::<Key, S, A>::contains ](m: &HashSet<Key, S, A>, k: &Q) -> (result: bool)
1078    ensures
1079        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> result
1080            == set_contains_borrowed_key(m@, k),
1081;
1082
1083// The specification for `get` has a parameter `key: &Q` where you'd
1084// expect to find `key: &Key`. This allows for the case that `Key` can
1085// be borrowed as something other than `&Key`. For instance,
1086// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
1087// as `&str`, so in those cases `Q` would be `u32` and `str`
1088// respectively.
1089// To deal with this, we have a specification function that opaquely
1090// specifies what it means for a returned reference to point to an
1091// element of a HashSet. And the postcondition of `get` says that
1092// its result matches the output of that specification function. (It
1093// also says that its result corresponds to the output of
1094// `contains_borrowed_key`, discussed above.) But this isn't very
1095// helpful by itself, since there's no body to that specification
1096// function. So we have special-case axioms that say what this means
1097// in two important circumstances: (1) `Key = Q` and (2) `Key =
1098// Box<Q>`.
1099pub uninterp spec fn sets_borrowed_key_to_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q, v: &Key) -> bool;
1100
1101pub broadcast proof fn axiom_set_deref_key_to_value<Q>(m: Set<Q>, k: &Q, v: &Q)
1102    ensures
1103        #[trigger] sets_borrowed_key_to_key::<Q, Q>(m, k, v) <==> m.contains(*k) && k == v,
1104{
1105    admit();
1106}
1107
1108pub broadcast proof fn axiom_set_box_key_to_value<Q>(m: Set<Box<Q>>, q: &Q, v: &Box<Q>)
1109    ensures
1110        #[trigger] sets_borrowed_key_to_key::<Box<Q>, Q>(m, q, v) <==> (m.contains(*v) && Box::new(
1111            *q,
1112        ) == v),
1113{
1114    admit();
1115}
1116
1117pub assume_specification<
1118    'a,
1119    Key: Borrow<Q> + Hash + Eq,
1120    S: BuildHasher,
1121    A: Allocator,
1122    Q: Hash + Eq + ?Sized,
1123>[ HashSet::<Key, S, A>::get::<Q> ](m: &'a HashSet<Key, S, A>, k: &Q) -> (result: Option<&'a Key>)
1124    ensures
1125        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> match result {
1126            Some(v) => sets_borrowed_key_to_key(m@, k, v),
1127            None => !set_contains_borrowed_key(m@, k),
1128        },
1129;
1130
1131// The specification for `remove` has a parameter `key: &Q` where
1132// you'd expect to find `key: &Key`. This allows for the case that
1133// `Key` can be borrowed as something other than `&Key`. For instance,
1134// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
1135// as `&str`, so in those cases `Q` would be `u32` and `str`
1136// respectively. To deal with this, we have a specification function
1137// that opaquely specifies what it means for two sets to be related by
1138// a remove of a certain `&Q`. And the postcondition of `remove` says
1139// that `old(self)@` and `self@` satisfy that relationship. (It also
1140// says that its result corresponds to the output of
1141// `set_contains_borrowed_key`, discussed above.) But this isn't very
1142// helpful by itself, since there's no body to that specification
1143// function. So we have special-case axioms that say what this means
1144// in two important circumstances: (1) `Key = Q` and (2) `Key = Box<Q>`.
1145pub uninterp spec fn sets_differ_by_borrowed_key<Key, Q: ?Sized>(
1146    old_m: Set<Key>,
1147    new_m: Set<Key>,
1148    k: &Q,
1149) -> bool;
1150
1151pub broadcast proof fn axiom_set_deref_key_removed<Q>(old_m: Set<Q>, new_m: Set<Q>, k: &Q)
1152    ensures
1153        #[trigger] sets_differ_by_borrowed_key::<Q, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
1154            *k,
1155        ),
1156{
1157    admit();
1158}
1159
1160pub broadcast proof fn axiom_set_box_key_removed<Q>(old_m: Set<Box<Q>>, new_m: Set<Box<Q>>, q: &Q)
1161    ensures
1162        #[trigger] sets_differ_by_borrowed_key::<Box<Q>, Q>(old_m, new_m, q) <==> new_m
1163            == old_m.remove(Box::new(*q)),
1164{
1165    admit();
1166}
1167
1168pub assume_specification<
1169    Key: Borrow<Q> + Hash + Eq,
1170    S: BuildHasher,
1171    A: Allocator,
1172    Q: Hash + Eq + ?Sized,
1173>[ HashSet::<Key, S, A>::remove::<Q> ](m: &mut HashSet<Key, S, A>, k: &Q) -> (result: bool)
1174    ensures
1175        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1176            &&& sets_differ_by_borrowed_key(old(m)@, final(m)@, k)
1177            &&& result == set_contains_borrowed_key(old(m)@, k)
1178        },
1179;
1180
1181pub assume_specification<Key, S, A: Allocator>[ HashSet::<Key, S, A>::clear ](
1182    m: &mut HashSet<Key, S, A>,
1183)
1184    ensures
1185        final(m)@ == Set::<Key>::empty(),
1186;
1187
1188// To allow reasoning about the ghost keys in the HashSet iterator when the executable
1189// function `iter()` is invoked in a `for` loop header (e.g., in
1190// `for x in it: m.keys() { ... }`), we need to specify the behavior of
1191// the iterator in spec mode. To do that, we add
1192// `#[verifier::when_used_as_spec(spec_iter)` to the specification for
1193// the executable `iter` method and define that spec function here.
1194pub uninterp spec fn spec_hash_keys_iter<'a, Key, S, A: Allocator>(m: &'a HashSet<Key, S, A>) -> (r:
1195    hash_set::Iter<'a, Key>);
1196
1197pub broadcast proof fn axiom_spec_hash_keys_iter<'a, Key, S, A: Allocator>(
1198    m: &'a HashSet<Key, S, A>,
1199)
1200    ensures
1201        (#[trigger] spec_hash_keys_iter(m).remaining()).unref().to_set() == m@,
1202        spec_hash_keys_iter(m).remaining().no_duplicates(),
1203        spec_hash_keys_iter(m).remaining().len() == m@.len(),
1204{
1205    admit();
1206}
1207
1208#[verifier::when_used_as_spec(spec_hash_keys_iter)]
1209pub assume_specification<'a, Key, S, A: Allocator>[ HashSet::<Key, S, A>::iter ](
1210    m: &'a HashSet<Key, S, A>,
1211) -> (hash_keys: hash_set::Iter<'a, Key>)
1212    ensures
1213        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> {
1214            &&& hash_keys == spec_hash_keys_iter(m)
1215            &&& IteratorSpec::decrease(&hash_keys) is Some
1216            &&& IteratorSpec::initial_value_relation(&hash_keys, &hash_keys)
1217        },
1218;
1219
1220pub broadcast proof fn axiom_hashset_decreases<Key, S, A: Allocator>(m: HashSet<Key, S, A>)
1221    ensures
1222        #[trigger] (decreases_to!(m => m@)),
1223{
1224    admit();
1225}
1226
1227//////// Entry API
1228// Specs for OccupiedEntry, VacantEntry, and the Entry enum
1229// OccupiedEntry and VacantEntry are both opaque;
1230// Entry is just an enum wrapper around the other 2, so we leave it transparent.
1231#[verifier::reject_recursive_types_in_ground_variants(K)]
1232#[verifier::reject_recursive_types_in_ground_variants(V)]
1233#[verifier::reject_recursive_types(A)]
1234#[verifier::external_body]
1235#[verifier::external_type_specification]
1236pub struct ExOccupiedEntry<'a, K: 'a, V: 'a, A: Allocator>(OccupiedEntry<'a, K, V, A>);
1237
1238#[verifier::reject_recursive_types_in_ground_variants(K)]
1239#[verifier::accept_recursive_types(V)]
1240#[verifier::reject_recursive_types(A)]
1241#[verifier::external_body]
1242#[verifier::external_type_specification]
1243pub struct ExVacantEntry<'a, K: 'a, V: 'a, A: Allocator>(VacantEntry<'a, K, V, A>);
1244
1245#[verifier::external_type_specification]
1246#[verifier::reject_recursive_types(A)]
1247pub struct ExEntry<'a, K: 'a, V: 'a, A: Allocator>(Entry<'a, K, V, A>);
1248
1249/// Specification for an [`OccupiedEntry`].
1250/// Contains the current key and value in the entry,
1251/// and prophesies the final value after this instantiation of the entry API is complete.
1252/// The final value is optional, since the user might choose to remove the entry.
1253pub trait OccupiedEntrySpecFns<K, V, A>: Sized {
1254    spec fn spec_key(self) -> K;
1255
1256    spec fn value(self) -> V;
1257
1258    #[verifier::prophetic]
1259    spec fn final_value(self) -> Option<V>;
1260}
1261
1262impl<'a, K, V, A: Allocator> OccupiedEntrySpecFns<K, V, A> for OccupiedEntry<'a, K, V, A> {
1263    uninterp spec fn spec_key(self) -> K;
1264
1265    uninterp spec fn value(self) -> V;
1266
1267    #[verifier::prophetic]
1268    uninterp spec fn final_value(self) -> Option<V>;
1269}
1270
1271/// Specification for a [`VacantEntry`].
1272/// Contains the current key for the entry,
1273/// and prophesies the final value after this instantiation of the entry API is complete.
1274/// The final value is optional, since the user may or may not choose to insert a value.
1275pub trait VacantEntrySpecFns<K, V, A>: Sized {
1276    spec fn spec_key(self) -> K;
1277
1278    #[verifier::prophetic]
1279    spec fn final_value(self) -> Option<V>;
1280}
1281
1282impl<'a, K, V, A: Allocator> VacantEntrySpecFns<K, V, A> for VacantEntry<'a, K, V, A> {
1283    uninterp spec fn spec_key(self) -> K;
1284
1285    #[verifier::prophetic]
1286    uninterp spec fn final_value(self) -> Option<V>;
1287}
1288
1289/// Specification for an [`Entry`].
1290/// Contains the current key for the entry,
1291/// and prophesies the final value after this instantiation of the entry API is complete.
1292pub trait EntrySpecFns<K, V, A>: Sized {
1293    spec fn spec_key(self) -> K;
1294
1295    spec fn value(self) -> Option<V>;
1296
1297    #[verifier::prophetic]
1298    spec fn final_value(self) -> Option<V>;
1299}
1300
1301impl<'a, K, V, A: Allocator> EntrySpecFns<K, V, A> for Entry<'a, K, V, A> {
1302    open spec fn spec_key(self) -> K {
1303        match self {
1304            Entry::Occupied(occupied_entry) => occupied_entry.spec_key(),
1305            Entry::Vacant(vacant_entry) => vacant_entry.spec_key(),
1306        }
1307    }
1308
1309    open spec fn value(self) -> Option<V> {
1310        match self {
1311            Entry::Occupied(occupied_entry) => Some(occupied_entry.value()),
1312            Entry::Vacant(vacant_entry) => None,
1313        }
1314    }
1315
1316    #[verifier::prophetic]
1317    open spec fn final_value(self) -> Option<V> {
1318        match self {
1319            Entry::Occupied(occupied_entry) => occupied_entry.final_value(),
1320            Entry::Vacant(vacant_entry) => vacant_entry.final_value(),
1321        }
1322    }
1323}
1324
1325pub broadcast axiom fn axiom_has_resolved_occupied_entry<K, V, A: Allocator>(
1326    entry: OccupiedEntry<K, V, A>,
1327)
1328    ensures
1329        #[trigger] has_resolved(entry) ==> entry.final_value() == Some(entry.value()),
1330;
1331
1332pub broadcast axiom fn axiom_has_resolved_vacant_entry<K, V, A: Allocator>(
1333    entry: VacantEntry<K, V, A>,
1334)
1335    ensures
1336        #[trigger] has_resolved(entry) ==> entry.final_value() == None::<V>,
1337;
1338
1339pub broadcast proof fn axiom_has_resolved_entry<K, V, A: Allocator>(entry: Entry<K, V, A>)
1340    ensures
1341        #[trigger] has_resolved(entry) ==> entry.final_value() == entry.value(),
1342{
1343    broadcast use axiom_has_resolved_occupied_entry;
1344    broadcast use axiom_has_resolved_vacant_entry;
1345
1346}
1347
1348pub assume_specification<'a, Key: Hash + Eq, Value, S: BuildHasher, A: Allocator>[ HashMap::<
1349    Key,
1350    Value,
1351    S,
1352    A,
1353>::entry ](m: &'a mut HashMap<Key, Value, S, A>, key: Key) -> (entry: Entry<'a, Key, Value, A>)
1354    ensures
1355        obeys_key_model::<Key>() && builds_valid_hashers::<S>() ==> (entry.key() == key
1356            && entry.value() == old(m)@.get(key) && final(m)@ == (match entry.final_value() {
1357            Some(value) => old(m)@.insert(key, value),
1358            None => old(m)@.remove(key),
1359        })),
1360;
1361
1362//// Entry
1363#[verifier::allow_in_spec]
1364pub assume_specification<'a, 'b, K, V, A: Allocator>[ Entry::key ](
1365    entry: &'b Entry::<'a, K, V, A>,
1366) -> (key: &'b K)
1367    returns
1368        &entry.spec_key(),
1369;
1370
1371pub assume_specification<'a, K, V, A: Allocator>[ Entry::or_insert ](
1372    entry: Entry::<'a, K, V, A>,
1373    default: V,
1374) -> (value: &'a mut V)
1375    ensures
1376        *value == (match entry.value() {
1377            Some(v) => v,
1378            None => default,
1379        }),
1380        entry.final_value() == Some(*final(value)),
1381;
1382
1383pub assume_specification<'a, K, V, A: Allocator>[ Entry::insert_entry ](
1384    entry: Entry::<'a, K, V, A>,
1385    value: V,
1386) -> (occ_entry: OccupiedEntry<'a, K, V, A>)
1387    ensures
1388        occ_entry.key() == entry.key(),
1389        occ_entry.value() == value,
1390        entry.final_value() == occ_entry.final_value(),
1391;
1392
1393//// OccupiedEntry
1394// This module works around a bug with `allow_in_spec` that creates duplicate spec fn names
1395mod m_occ {
1396    use super::*;
1397
1398    #[verifier::allow_in_spec]
1399    pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::key ](
1400        entry: &'b OccupiedEntry::<'a, K, V, A>,
1401    ) -> (key: &'b K)
1402        returns
1403            &entry.spec_key(),
1404    ;
1405
1406}
1407
1408pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::remove_entry ](
1409    entry: OccupiedEntry::<'a, K, V, A>,
1410) -> (kv: (K, V))
1411    ensures
1412        entry.final_value() == None,
1413    returns
1414        (*entry.key(), entry.value()),
1415;
1416
1417pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::get ](
1418    entry: &'b OccupiedEntry::<'a, K, V, A>,
1419) -> (value: &'b V)
1420    ensures
1421        *value == entry.value(),
1422;
1423
1424pub assume_specification<'a, 'b, K, V, A: Allocator>[ OccupiedEntry::get_mut ](
1425    entry: &'b mut OccupiedEntry::<'a, K, V, A>,
1426) -> (value: &'b mut V)
1427    ensures
1428        *value == old(entry).value(),
1429        final(entry).key() == old(entry).key(),
1430        final(entry).value() == *final(value),
1431        final(entry).final_value() == old(entry).final_value(),
1432;
1433
1434pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::into_mut ](
1435    entry: OccupiedEntry::<'a, K, V, A>,
1436) -> (value: &mut V)
1437    ensures
1438        *value == entry.value(),
1439        entry.final_value() == Some(*final(value)),
1440;
1441
1442pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::insert ](
1443    entry: &mut OccupiedEntry::<'a, K, V, A>,
1444    value: V,
1445) -> (old_value: V)
1446    ensures
1447        old_value == old(entry).value(),
1448        final(entry).key() == old(entry).key(),
1449        final(entry).value() == value,
1450        final(entry).final_value() == old(entry).final_value(),
1451;
1452
1453pub assume_specification<'a, K, V, A: Allocator>[ OccupiedEntry::remove ](
1454    entry: OccupiedEntry::<'a, K, V, A>,
1455) -> (value: V)
1456    ensures
1457        value == entry.value(),
1458        entry.final_value() == None,
1459;
1460
1461//// VacantEntry
1462// This module works around a bug with `allow_in_spec` that creates duplicate spec fn names
1463mod m_vac {
1464    use super::*;
1465
1466    #[verifier::allow_in_spec]
1467    pub assume_specification<'a, 'b, K: 'a, V: 'a, A: Allocator>[ VacantEntry::key ](
1468        entry: &'b VacantEntry::<'a, K, V, A>,
1469    ) -> (key: &'b K)
1470        returns
1471            &entry.spec_key(),
1472    ;
1473
1474}
1475
1476pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::into_key ](
1477    entry: VacantEntry::<'a, K, V, A>,
1478) -> (key: K)
1479    ensures
1480        key == entry.key(),
1481        entry.final_value() == None,
1482;
1483
1484pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::insert ](
1485    entry: VacantEntry::<'a, K, V, A>,
1486    value: V,
1487) -> (value_ref: &mut V)
1488    ensures
1489        *value_ref == value,
1490        entry.final_value() == Some(*final(value_ref)),
1491;
1492
1493pub assume_specification<'a, K: 'a, V: 'a, A: Allocator>[ VacantEntry::insert_entry ](
1494    entry: VacantEntry::<'a, K, V, A>,
1495    value: V,
1496) -> (occ_entry: OccupiedEntry::<'a, K, V, A>)
1497    ensures
1498        occ_entry.key() == entry.key(),
1499        occ_entry.value() == value,
1500        entry.final_value() == occ_entry.final_value(),
1501;
1502
1503pub broadcast group group_hash_axioms {
1504    axiom_box_key_removed,
1505    axiom_contains_deref_key,
1506    axiom_contains_box,
1507    axiom_deref_key_removed,
1508    axiom_maps_deref_key_to_value,
1509    axiom_maps_box_key_to_value,
1510    axiom_hashmap_deepview_borrow,
1511    axiom_hashmap_view_finite_dom,
1512    axiom_bool_obeys_hash_table_key_model,
1513    axiom_u8_obeys_hash_table_key_model,
1514    axiom_u16_obeys_hash_table_key_model,
1515    axiom_u32_obeys_hash_table_key_model,
1516    axiom_u64_obeys_hash_table_key_model,
1517    axiom_u128_obeys_hash_table_key_model,
1518    axiom_usize_obeys_hash_table_key_model,
1519    axiom_i8_obeys_hash_table_key_model,
1520    axiom_i16_obeys_hash_table_key_model,
1521    axiom_i32_obeys_hash_table_key_model,
1522    axiom_i64_obeys_hash_table_key_model,
1523    axiom_i128_obeys_hash_table_key_model,
1524    axiom_isize_obeys_hash_table_key_model,
1525    axiom_box_bool_obeys_hash_table_key_model,
1526    axiom_box_integer_type_obeys_hash_table_key_model,
1527    axiom_random_state_builds_valid_hashers,
1528    axiom_spec_hash_map_len,
1529    axiom_set_box_key_removed,
1530    axiom_set_contains_deref_key,
1531    axiom_set_contains_box,
1532    axiom_set_deref_key_removed,
1533    axiom_set_deref_key_to_value,
1534    axiom_set_box_key_to_value,
1535    axiom_spec_hash_set_len,
1536    axiom_spec_hash_map_iter,
1537    axiom_spec_hash_keys_iter,
1538    axiom_spec_keys_iter,
1539    axiom_spec_values_iter,
1540    axiom_hashmap_decreases,
1541    axiom_hashset_decreases,
1542    axiom_has_resolved_occupied_entry,
1543    axiom_has_resolved_vacant_entry,
1544    axiom_has_resolved_entry,
1545}
1546
1547} // verus!