Skip to main content

vstd/std_specs/
btree.rs

1//! This code adds specifications for the standard-library types
2//! `alloc::collections::BTreeMap` and `alloc::collections::BTreeSet`.
3//!
4//! The specification is only meaningful when the `Key` obeys our [`Ord`] model,
5//! as specified by [`super::super::laws_cmp::obeys_cmp_spec`].
6//!
7//! By default, the Verus standard library brings useful axioms
8//! about the behavior of `BTreeMap` and `BTreeSet` into the ambient
9//! reasoning context by broadcasting the group
10//! `vstd::std_specs::btree::group_btree_axioms`.
11use super::super::laws_cmp::obeys_cmp;
12use super::super::prelude::*;
13use super::cmp::OrdSpec;
14use super::iter::IteratorSpec;
15
16#[cfg(verus_keep_ghost)]
17use super::super::map::assert_maps_equal;
18
19use alloc::alloc::Allocator;
20use alloc::boxed::Box;
21use alloc::collections::btree_map;
22use alloc::collections::btree_map::{CursorMut, Keys, UnorderedKeyError, Values};
23use alloc::collections::btree_set;
24use alloc::collections::{BTreeMap, BTreeSet};
25use core::borrow::Borrow;
26use core::cmp::Ordering;
27use core::marker::PhantomData;
28use core::ops::Bound;
29use core::option::Option;
30
31verus! {
32
33/// Whether the `Key` type obeys the cmp spec, required for [`BTreeMap`]
34///
35/// This is a workaround to the fact that [`BTreeMap`] "late binds" the trait bounds when needed.
36/// For instance, [`BTreeMap::iter`] does not require `Key: Ord`, even though it yields ordered
37/// items. Rather, it relies on the fact that [`BTreeMap::insert`] does require `Key: Ord`, meaning
38/// no instance of a [`BTreeMap`] will ever have keys that cannot be comparable.
39///
40/// See also [`axiom_key_obeys_cmp_spec_meaning`].
41pub uninterp spec fn key_obeys_cmp_spec<Key: ?Sized>() -> bool;
42
43/// For types that are ordered, [`key_obeys_cmp_spec`] is equivalent to [`obeys_cmp`].
44pub broadcast axiom fn axiom_key_obeys_cmp_spec_meaning<K: Ord>()
45    ensures
46        #[trigger] key_obeys_cmp_spec::<K>() <==> obeys_cmp::<K>(),
47;
48
49/// Whether a sequence is ordered in increasing order.
50/// This only has meaning if `K: Ord` and [`obeys_cmp::<K>`].
51///
52/// See [`axiom_increasing_seq_meaning`] for an interpretation of this predicate.
53pub uninterp spec fn increasing_seq<K>(s: Seq<K>) -> bool;
54
55/// An interpretation for the [`increasing_seq`] predicate.
56pub broadcast axiom fn axiom_increasing_seq_meaning<K: Ord>(s: Seq<K>)
57    requires
58        obeys_cmp::<K>(),
59    ensures
60        #[trigger] increasing_seq(s) <==> forall|i, j|
61            0 <= i < j < s.len() ==> s[i].cmp_spec(&s[j]) is Less,
62;
63
64/// Specifications for the behavior of
65/// [`alloc::collections::btree_map::Keys`](https://doc.rust-lang.org/alloc/collections/btree_map/struct.Keys.html).
66#[verifier::external_type_specification]
67#[verifier::external_body]
68#[verifier::accept_recursive_types(Key)]
69#[verifier::accept_recursive_types(Value)]
70pub struct ExKeys<'a, Key, Value>(Keys<'a, Key, Value>);
71
72// To allow reasoning about the "contents" of the Keys iterator, without using
73// a prophecy, we need a function that gives us the underlying sequence of the original keys.
74pub uninterp spec fn into_iter_keys<'a, Key, Value>(i: Keys<'a, Key, Value>) -> Seq<Key>;
75
76impl<'a, K, V> super::iter::IteratorSpecImpl for Keys<'a, K, V> {
77    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
78        true
79    }
80
81    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
82
83    uninterp spec fn will_return_none(&self) -> bool;
84
85    uninterp spec fn decrease(&self) -> Option<nat>;
86
87    open spec fn peek(&self, index: int) -> Option<Self::Item> {
88        if 0 <= index < into_iter_keys(*self).len() {
89            Some(&into_iter_keys(*self)[index])
90        } else {
91            None
92        }
93    }
94}
95
96/// Specifications for the behavior of
97/// [`alloc::collections::btree_map::Values`](https://doc.rust-lang.org/alloc/collections/btree_map/struct.Values.html).
98#[verifier::external_type_specification]
99#[verifier::external_body]
100#[verifier::accept_recursive_types(Key)]
101#[verifier::accept_recursive_types(Value)]
102pub struct ExValues<'a, Key, Value>(Values<'a, Key, Value>);
103
104// To allow reasoning about the "contents" of the Values iterator, without using
105// a prophecy, we need a function that gives us the underlying sequence of the original values.
106pub uninterp spec fn into_iter_values<'a, Key, Value>(i: Values<'a, Key, Value>) -> Seq<Value>;
107
108impl<'a, K, V> super::iter::IteratorSpecImpl for Values<'a, K, V> {
109    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
110        true
111    }
112
113    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
114
115    uninterp spec fn will_return_none(&self) -> bool;
116
117    uninterp spec fn decrease(&self) -> Option<nat>;
118
119    open spec fn peek(&self, index: int) -> Option<Self::Item> {
120        if 0 <= index < into_iter_values(*self).len() {
121            Some(&into_iter_values(*self)[index])
122        } else {
123            None
124        }
125    }
126}
127
128// The `iter` method of a `BTreeMap` returns an iterator of type `btree_map::Iter`,
129// so we specify that type here.
130#[verifier::external_type_specification]
131#[verifier::external_body]
132#[verifier::accept_recursive_types(K)]
133#[verifier::accept_recursive_types(V)]
134pub struct ExMapIter<'a, K, V>(btree_map::Iter<'a, K, V>);
135
136// To allow reasoning about the "contents" of the Iter iterator, without using
137// a prophecy, we need a function that gives us the underlying sequence of the original map.
138pub uninterp spec fn into_iter<'a, Key, Value>(i: btree_map::Iter<'a, Key, Value>) -> Seq<
139    (Key, Value),
140>;
141
142impl<'a, K, V> super::iter::IteratorSpecImpl for btree_map::Iter<'a, K, V> {
143    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
144        true
145    }
146
147    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
148
149    uninterp spec fn will_return_none(&self) -> bool;
150
151    uninterp spec fn decrease(&self) -> Option<nat>;
152
153    open spec fn peek(&self, index: int) -> Option<Self::Item> {
154        if 0 <= index < into_iter(*self).len() {
155            let (k, v) = into_iter(*self)[index];
156            Some((&k, &v))
157        } else {
158            None
159        }
160    }
161}
162
163pub assume_specification<'a, Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::iter ](
164    m: &'a BTreeMap<Key, Value, A>,
165) -> (iter: btree_map::Iter<'a, Key, Value>)
166    ensures
167        key_obeys_cmp_spec::<Key>() ==> {
168            &&& IteratorSpec::remaining(&iter).len() == m@.dom().len()
169            &&& forall|i: int|
170                #![trigger m@.contains_key(*IteratorSpec::remaining(&iter)[i].0)]
171                #![trigger m@[*IteratorSpec::remaining(&iter)[i].0]]
172                0 <= i < IteratorSpec::remaining(&iter).len() ==> m@.contains_key(
173                    *IteratorSpec::remaining(&iter)[i].0,
174                ) && m@[*IteratorSpec::remaining(&iter)[i].0] == *IteratorSpec::remaining(
175                    &iter,
176                )[i].1
177            &&& forall|k: Key| #[trigger]
178                m@.contains_key(k) ==> IteratorSpec::remaining(&iter).contains((&k, &m@[k]))
179            &&& IteratorSpec::remaining(&iter).unref().to_set() == m@.kv_pairs()
180            &&& iter.remaining().no_duplicates()
181            &&& into_iter(iter) == IteratorSpec::remaining(&iter).unref()
182            &&& IteratorSpec::decrease(&iter) is Some
183            &&& increasing_seq(iter.remaining().map_values(|kv: (&Key, &Value)| *kv.0))
184        },
185;
186
187/// Specifications for the behavior of [`alloc::collections::BTreeMap`](https://doc.rust-lang.org/alloc/collections/struct.BTreeMap.html).
188///
189/// We model a `BTreeMap` as having a view of type `Map<Key, Value>`, which reflects the current state of the map.
190///
191/// These specifications are only meaningful if `key_obeys_cmp_spec::<Key>()` holds.
192/// See [`key_obeys_cmp_spec`] for information on use with primitive types and other types.
193///
194/// Axioms about the behavior of BTreeMap are present in the broadcast group `vstd::std_specs::btree::group_btree_axioms`.
195#[verifier::external_type_specification]
196#[verifier::external_body]
197#[verifier::accept_recursive_types(Key)]
198#[verifier::accept_recursive_types(Value)]
199#[verifier::reject_recursive_types(A)]
200pub struct ExBTreeMap<Key, Value, A: Allocator + Clone>(BTreeMap<Key, Value, A>);
201
202/// Verus declaration for Rust's mutable B-tree cursor type.
203#[verifier::external_type_specification]
204#[verifier::external_body]
205#[verifier::accept_recursive_types(Key)]
206#[verifier::accept_recursive_types(Value)]
207#[verifier::reject_recursive_types(A)]
208pub struct ExCursorMut<'a, Key: 'a, Value: 'a, A>(CursorMut<'a, Key, Value, A>);
209
210/// Verus declaration for the error returned when a cursor insertion would break key ordering.
211#[verifier::external_type_specification]
212#[verifier::external_body]
213pub struct ExUnorderedKeyError(UnorderedKeyError);
214
215/// The abstract state of a mutable B-tree cursor.
216///
217/// A cursor points at the gap immediately before `keys[position]`. Therefore, `peek_next`
218/// accesses `keys[position]`, while `peek_prev` accesses `keys[position - 1]`.
219pub ghost struct CursorMutModel<Key, Value> {
220    /// All keys in the underlying map, in strictly increasing order.
221    pub keys: Seq<Key>,
222    /// The index of the element immediately after the cursor.
223    pub position: int,
224    /// The current contents of the complete map borrowed by the cursor.
225    pub map: Map<Key, Value>,
226}
227
228impl<Key, Value> CursorMutModel<Key, Value> {
229    /// Whether this model consistently represents an ordered map and a gap in that map.
230    pub open spec fn wf(self) -> bool {
231        &&& 0 <= self.position <= self.keys.len()
232        &&& self.keys.no_duplicates()
233        &&& self.keys.to_set() == self.map.dom()
234        &&& increasing_seq(self.keys)
235    }
236}
237
238/// Abstract and prophetic state for mutable B-tree cursors.
239pub trait CursorMutSpecFns<Key, Value>: View<V = CursorMutModel<Key, Value>> + Sized {
240    /// The contents of the borrowed map when this cursor's borrow is resolved.
241    #[verifier::prophetic]
242    spec fn final_map(self) -> Map<Key, Value>;
243}
244
245impl<'a, Key, Value, A> View for CursorMut<'a, Key, Value, A> {
246    type V = CursorMutModel<Key, Value>;
247
248    uninterp spec fn view(&self) -> CursorMutModel<Key, Value>;
249}
250
251impl<'a, Key, Value, A> CursorMutSpecFns<Key, Value> for CursorMut<'a, Key, Value, A> {
252    #[verifier::prophetic]
253    uninterp spec fn final_map(self) -> Map<Key, Value>;
254}
255
256/// Whether a borrowed key type's ordering agrees with the ordering of stored keys.
257///
258/// This is the semantic requirement imposed on `Key: Borrow<Q>` by the standard library's
259/// borrowed-key `BTreeMap` operations.
260pub uninterp spec fn borrowed_key_ordering_matches<Key: Borrow<Q> + Ord, Q: Ord + ?Sized>() -> bool;
261
262/// A key type has the same ordering as itself.
263pub broadcast axiom fn axiom_deref_key_ordering_matches<Key: Ord>()
264    ensures
265        #[trigger] borrowed_key_ordering_matches::<Key, Key>(),
266;
267
268/// The ordering of a stored key relative to a borrowed lookup key.
269pub uninterp spec fn borrowed_key_cmp<Key, Q: ?Sized>(stored_key: Key, key: &Q) -> Ordering;
270
271/// Comparing a stored key against a borrowed key of the same type agrees with [`OrdSpec`].
272pub broadcast axiom fn axiom_deref_key_cmp<Key: Ord>(stored_key: Key, key: &Key)
273    ensures
274        #[trigger] borrowed_key_cmp::<Key, Key>(stored_key, key) == stored_key.cmp_spec(key),
275;
276
277/// Whether a key occurs before the gap returned by [`BTreeMap::lower_bound_mut`].
278pub open spec fn before_lower_bound<Key, Q: ?Sized>(key: Key, bound: Bound<&Q>) -> bool {
279    match bound {
280        Bound::Included(bound_key) => borrowed_key_cmp(key, bound_key) is Less,
281        Bound::Excluded(bound_key) => !(borrowed_key_cmp(key, bound_key) is Greater),
282        Bound::Unbounded => false,
283    }
284}
285
286/// Whether a key occurs before the gap returned by [`BTreeMap::upper_bound_mut`].
287pub open spec fn before_upper_bound<Key, Q: ?Sized>(key: Key, bound: Bound<&Q>) -> bool {
288    match bound {
289        Bound::Included(bound_key) => !(borrowed_key_cmp(key, bound_key) is Greater),
290        Bound::Excluded(bound_key) => borrowed_key_cmp(key, bound_key) is Less,
291        Bound::Unbounded => true,
292    }
293}
294
295/// Whether a cursor is at the gap selected by [`BTreeMap::lower_bound_mut`].
296pub open spec fn positioned_at_lower_bound<Key, Value, Q: ?Sized>(
297    model: CursorMutModel<Key, Value>,
298    bound: Bound<&Q>,
299) -> bool {
300    &&& forall|i: int|
301        #![trigger before_lower_bound(model.keys[i], bound)]
302        0 <= i < model.position ==> before_lower_bound(model.keys[i], bound)
303    &&& forall|i: int|
304        #![trigger before_lower_bound(model.keys[i], bound)]
305        model.position <= i < model.keys.len() ==> !before_lower_bound(model.keys[i], bound)
306}
307
308/// Whether a cursor is at the gap selected by [`BTreeMap::upper_bound_mut`].
309pub open spec fn positioned_at_upper_bound<Key, Value, Q: ?Sized>(
310    model: CursorMutModel<Key, Value>,
311    bound: Bound<&Q>,
312) -> bool {
313    &&& forall|i: int|
314        #![trigger before_upper_bound(model.keys[i], bound)]
315        0 <= i < model.position ==> before_upper_bound(model.keys[i], bound)
316    &&& forall|i: int|
317        #![trigger before_upper_bound(model.keys[i], bound)]
318        model.position <= i < model.keys.len() ==> !before_upper_bound(model.keys[i], bound)
319}
320
321/// Whether a key can be inserted at the cursor's current gap without breaking key order.
322pub open spec fn key_fits_at_position<Key: Ord, Value>(
323    model: CursorMutModel<Key, Value>,
324    key: Key,
325) -> bool {
326    &&& (model.position == 0 || model.keys[model.position - 1].cmp_spec(&key) is Less)
327    &&& (model.position == model.keys.len() || key.cmp_spec(&model.keys[model.position]) is Less)
328}
329
330/// Once the cursor has been dropped, its prophesied map is its current map.
331pub broadcast axiom fn axiom_has_resolved_cursor<Key, Value, A>(cursor: CursorMut<Key, Value, A>)
332    ensures
333        #[trigger] has_resolved(cursor) ==> cursor.final_map() == cursor@.map,
334;
335
336pub trait BTreeMapAdditionalSpecFns<Key, Value>: View<V = Map<Key, Value>> {
337    spec fn spec_index(&self, k: Key) -> Value
338        recommends
339            self@.contains_key(k),
340    ;
341}
342
343impl<Key, Value, A: Allocator + Clone> BTreeMapAdditionalSpecFns<Key, Value> for BTreeMap<
344    Key,
345    Value,
346    A,
347> {
348    #[verifier::inline]
349    open spec fn spec_index(&self, k: Key) -> Value {
350        self@.index(k)
351    }
352}
353
354impl<Key, Value, A: Allocator + Clone> View for BTreeMap<Key, Value, A> {
355    type V = Map<Key, Value>;
356
357    uninterp spec fn view(&self) -> Map<Key, Value>;
358}
359
360impl<Key: DeepView, Value: DeepView, A: Allocator + Clone> DeepView for BTreeMap<Key, Value, A> {
361    type V = Map<Key::V, Value::V>;
362
363    open spec fn deep_view(&self) -> Map<Key::V, Value::V> {
364        btree_map_deep_view_impl(*self)
365    }
366}
367
368/// The actual definition of `BTreeMap::deep_view`.
369///
370/// This is a separate function since it introduces a lot of quantifiers and revealing an opaque trait
371/// method is not supported. In most cases, it's easier to use one of the lemmas below instead
372/// of revealing this function directly.
373#[verifier::opaque]
374pub open spec fn btree_map_deep_view_impl<Key: DeepView, Value: DeepView, A: Allocator + Clone>(
375    m: BTreeMap<Key, Value, A>,
376) -> Map<Key::V, Value::V> {
377    Map::new(
378        m@.dom().map(|k: Key| k.deep_view()),
379        |dk: Key::V|
380            {
381                let k = choose|k: Key| m@.contains_key(k) && #[trigger] k.deep_view() == dk;
382                m@[k].deep_view()
383            },
384    )
385}
386
387pub broadcast proof fn lemma_btree_map_deepview_dom<K: DeepView, V: DeepView>(m: BTreeMap<K, V>)
388    ensures
389        #[trigger] m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()),
390{
391    reveal(btree_map_deep_view_impl);
392    broadcast use group_btree_axioms;
393    broadcast use crate::vstd::group_vstd_default;
394
395    assert(m.deep_view().dom() =~= m@.dom().map(|k: K| k.deep_view()));
396}
397
398pub broadcast proof fn lemma_btree_map_deepview_properties<K: DeepView, V: DeepView>(
399    m: BTreeMap<K, V>,
400)
401    requires
402        crate::relations::injective(|k: K| k.deep_view()),
403    ensures
404        #![trigger m.deep_view()]
405        // all elements in m.view() are present in m.deep_view()
406        forall|k: K| #[trigger]
407            m@.contains_key(k) ==> m.deep_view().contains_key(k.deep_view())
408                && m.deep_view()[k.deep_view()] == m@[k].deep_view(),
409        // all elements in m.deep_view() are present in m.view()
410        forall|dk: <K as DeepView>::V| #[trigger]
411            m.deep_view().contains_key(dk) ==> exists|k: K|
412                k.deep_view() == dk && #[trigger] m@.contains_key(k),
413{
414    reveal(btree_map_deep_view_impl);
415    broadcast use group_btree_axioms;
416    broadcast use crate::vstd::group_vstd_default;
417
418    assert(m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()));
419    assert forall|k: K| #[trigger] m@.contains_key(k) implies m.deep_view().contains_key(
420        k.deep_view(),
421    ) && m.deep_view()[k.deep_view()] == m@[k].deep_view() by {
422        assert forall|k1: K, k2: K| #[trigger]
423            k1.deep_view() == #[trigger] k2.deep_view() implies k1 == k2 by {
424            let ghost k_deepview = |k: K| k.deep_view();
425            assert(crate::relations::injective(k_deepview));
426            assert(k_deepview(k1) == k_deepview(k2));
427        }
428    }
429}
430
431pub broadcast proof fn lemma_btree_map_deepview_values<K: DeepView, V: DeepView>(m: BTreeMap<K, V>)
432    requires
433        crate::relations::injective(|k: K| k.deep_view()),
434    ensures
435        #[trigger] m.deep_view().values() =~= m@.values().map(|v: V| v.deep_view()),
436{
437    reveal(btree_map_deep_view_impl);
438    broadcast use group_btree_axioms;
439    broadcast use lemma_btree_map_deepview_properties;
440    broadcast use crate::vstd::group_vstd_default;
441
442    let lhs = m.deep_view().values();
443    let rhs = m@.values().map(|v: V| v.deep_view());
444    assert forall|v: V::V| #[trigger] lhs.contains(v) implies rhs.contains(v) by {
445        let dk = choose|dk: K::V| #[trigger]
446            m.deep_view().contains_key(dk) && m.deep_view()[dk] == v;
447        let k = choose|k: K| #[trigger] m@.contains_key(k) && k.deep_view() == dk;
448        let ov = choose|ov: V| #[trigger] m@.contains_key(k) && m@[k] == ov && ov.deep_view() == v;
449        assert(v == ov.deep_view());
450        assert(m@.values().contains(ov));
451    }
452}
453
454/// Borrowing a key works the same way on deep_view as on view,
455/// if deep_view is injective; see `axiom_contains_deref_key`.
456pub broadcast axiom fn axiom_btree_map_deepview_borrow<
457    K: DeepView + Borrow<Q>,
458    V: DeepView,
459    Q: View<V = <K as DeepView>::V> + Eq + ?Sized,
460>(m: BTreeMap<K, V>, k: &Q)
461    requires
462        key_obeys_cmp_spec::<K>(),
463        crate::relations::injective(|k: K| k.deep_view()),
464    ensures
465        #[trigger] contains_borrowed_key(m@, k) <==> m.deep_view().contains_key(k@),
466;
467
468pub uninterp spec fn spec_btree_map_len<Key, Value, A: Allocator + Clone>(
469    m: &BTreeMap<Key, Value, A>,
470) -> usize;
471
472pub broadcast axiom fn axiom_spec_btree_map_len<Key, Value, A: Allocator + Clone>(
473    m: &BTreeMap<Key, Value, A>,
474)
475    ensures
476        key_obeys_cmp_spec::<Key>() ==> #[trigger] spec_btree_map_len(m) == m@.len(),
477;
478
479#[verifier::when_used_as_spec(spec_btree_map_len)]
480pub assume_specification<Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::len ](
481    m: &BTreeMap<Key, Value, A>,
482) -> (len: usize)
483    ensures
484        len == spec_btree_map_len(m),
485;
486
487pub assume_specification<Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::is_empty ](
488    m: &BTreeMap<Key, Value, A>,
489) -> (res: bool)
490    ensures
491        res == m@.is_empty(),
492;
493
494pub assume_specification<K: Clone, V: Clone, A: Allocator + Clone>[ <BTreeMap::<
495    K,
496    V,
497    A,
498> as Clone>::clone ](this: &BTreeMap<K, V, A>) -> (other: BTreeMap<K, V, A>)
499    ensures
500        other@ == this@,
501;
502
503pub assume_specification<Key, Value>[ BTreeMap::<Key, Value>::new ]() -> (m: BTreeMap<Key, Value>)
504    ensures
505        m@ == Map::<Key, Value>::empty(),
506;
507
508pub assume_specification<K, V>[ <BTreeMap<K, V> as core::default::Default>::default ]() -> (m:
509    BTreeMap<K, V>)
510    ensures
511        m@ == Map::<K, V>::empty(),
512;
513
514pub assume_specification<Key: Ord, Value, A: Allocator + Clone>[ BTreeMap::<
515    Key,
516    Value,
517    A,
518>::insert ](m: &mut BTreeMap<Key, Value, A>, k: Key, v: Value) -> (result: Option<Value>)
519    ensures
520        obeys_cmp::<Key>() ==> {
521            &&& final(m)@ == old(m)@.insert(k, v)
522            &&& match result {
523                Some(v) => old(m)@.contains_key(k) && v == old(m)[k],
524                None => !old(m)@.contains_key(k),
525            }
526        },
527;
528
529// The specification for `contains_key` has a parameter `key: &Q`
530// where you'd expect to find `key: &Key`. This allows for the case
531// that `Key` can be borrowed as something other than `&Key`. For
532// instance, `Box<u32>` can be borrowed as `&u32` and `String` can be
533// borrowed as `&str`, so in those cases `Q` would be `u32` and `str`
534// respectively.
535// To deal with this, we have a specification function that opaquely
536// specifies what it means for a map to contain a borrowed key of type
537// `&Q`. And the postcondition of `contains_key` just says that its
538// result matches the output of that specification function. But this
539// isn't very helpful by itself, since there's no body to that
540// specification function. So we have special-case axioms that say
541// what this means in two important circumstances: (1) `Key = Q` and
542// (2) `Key = Box<Q>`.
543pub uninterp spec fn contains_borrowed_key<Key, Value, Q: ?Sized>(
544    m: Map<Key, Value>,
545    k: &Q,
546) -> bool;
547
548pub broadcast axiom fn axiom_contains_deref_key<Q, Value>(m: Map<Q, Value>, k: &Q)
549    ensures
550        #[trigger] contains_borrowed_key::<Q, Value, Q>(m, k) <==> m.contains_key(*k),
551;
552
553pub broadcast axiom fn axiom_contains_box<Q, Value>(m: Map<Box<Q>, Value>, k: &Q)
554    ensures
555        #[trigger] contains_borrowed_key::<Box<Q>, Value, Q>(m, k) <==> m.contains_key(
556            Box::new(*k),
557        ),
558;
559
560pub assume_specification<
561    Key: Borrow<Q> + Ord,
562    Value,
563    A: Allocator + Clone,
564    Q: Ord + ?Sized,
565>[ BTreeMap::<Key, Value, A>::contains_key::<Q> ](m: &BTreeMap<Key, Value, A>, k: &Q) -> (result:
566    bool)
567    ensures
568        obeys_cmp::<Key>() ==> result == contains_borrowed_key(m@, k),
569;
570
571// The specification for `get` has a parameter `key: &Q` where you'd
572// expect to find `key: &Key`. This allows for the case that `Key` can
573// be borrowed as something other than `&Key`. For instance,
574// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
575// as `&str`, so in those cases `Q` would be `u32` and `str`
576// respectively.
577// To deal with this, we have a specification function that opaquely
578// specifies what it means for a map to map a borrowed key of type
579// `&Q` to a certain value. And the postcondition of `get` says that
580// its result matches the output of that specification function. (It
581// also says that its result corresponds to the output of
582// `contains_borrowed_key`, discussed above.) But this isn't very
583// helpful by itself, since there's no body to that specification
584// function. So we have special-case axioms that say what this means
585// in two important circumstances: (1) `Key = Q` and (2) `Key =
586// Box<Q>`.
587pub uninterp spec fn maps_borrowed_key_to_value<Key, Value, Q: ?Sized>(
588    m: Map<Key, Value>,
589    k: &Q,
590    v: Value,
591) -> bool;
592
593pub broadcast axiom fn axiom_maps_deref_key_to_value<Q, Value>(m: Map<Q, Value>, k: &Q, v: Value)
594    ensures
595        #[trigger] maps_borrowed_key_to_value::<Q, Value, Q>(m, k, v) <==> m.contains_key(*k)
596            && m[*k] == v,
597;
598
599pub broadcast axiom fn axiom_maps_box_key_to_value<Q, Value>(m: Map<Box<Q>, Value>, q: &Q, v: Value)
600    ensures
601        #[trigger] maps_borrowed_key_to_value::<Box<Q>, Value, Q>(m, q, v) <==> {
602            let k = Box::new(*q);
603            &&& m.contains_key(k)
604            &&& m[k] == v
605        },
606;
607
608pub assume_specification<
609    'a,
610    Key: Borrow<Q> + Ord,
611    Value,
612    A: Allocator + Clone,
613    Q: Ord + ?Sized,
614>[ BTreeMap::<Key, Value, A>::get::<Q> ](m: &'a BTreeMap<Key, Value, A>, k: &Q) -> (result: Option<
615    &'a Value,
616>)
617    requires
618        borrowed_key_ordering_matches::<Key, Q>(),
619    ensures
620        obeys_cmp::<Key>() ==> match result {
621            Some(v) => maps_borrowed_key_to_value(m@, k, *v),
622            None => !contains_borrowed_key(m@, k),
623        },
624;
625
626// The specification for `remove` has a parameter `key: &Q` where
627// you'd expect to find `key: &Key`. This allows for the case that
628// `Key` can be borrowed as something other than `&Key`. For instance,
629// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
630// as `&str`, so in those cases `Q` would be `u32` and `str`
631// respectively. To deal with this, we have a specification function
632// that opaquely specifies what it means for two maps to be related by
633// a remove of a certain `&Q`. And the postcondition of `remove` says
634// that `old(self)@` and `self@` satisfy that relationship. (It also
635// says that its result corresponds to the output of
636// `contains_borrowed_key` and `maps_borrowed_key_to_value`, discussed
637// above.) But this isn't very helpful by itself, since there's no
638// body to that specification function. So we have special-case axioms
639// that say what this means in two important circumstances: (1) `Key =
640// Q` and (2) `Key = Box<Q>`.
641pub uninterp spec fn borrowed_key_removed<Key, Value, Q: ?Sized>(
642    old_m: Map<Key, Value>,
643    new_m: Map<Key, Value>,
644    k: &Q,
645) -> bool;
646
647pub broadcast axiom fn axiom_deref_key_removed<Q, Value>(
648    old_m: Map<Q, Value>,
649    new_m: Map<Q, Value>,
650    k: &Q,
651)
652    ensures
653        #[trigger] borrowed_key_removed::<Q, Value, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
654            *k,
655        ),
656;
657
658pub broadcast axiom fn axiom_box_key_removed<Q, Value>(
659    old_m: Map<Box<Q>, Value>,
660    new_m: Map<Box<Q>, Value>,
661    q: &Q,
662)
663    ensures
664        #[trigger] borrowed_key_removed::<Box<Q>, Value, Q>(old_m, new_m, q) <==> new_m
665            == old_m.remove(Box::new(*q)),
666;
667
668pub assume_specification<
669    Key: Borrow<Q> + Ord,
670    Value,
671    A: Allocator + Clone,
672    Q: Ord + ?Sized,
673>[ BTreeMap::<Key, Value, A>::remove::<Q> ](m: &mut BTreeMap<Key, Value, A>, k: &Q) -> (result:
674    Option<Value>)
675    ensures
676        obeys_cmp::<Key>() ==> {
677            &&& borrowed_key_removed(old(m)@, final(m)@, k)
678            &&& match result {
679                Some(v) => maps_borrowed_key_to_value(old(m)@, k, v),
680                None => !contains_borrowed_key(old(m)@, k),
681            }
682        },
683;
684
685/// Relates a map before and after mutating the value selected by a borrowed key.
686pub open spec fn borrowed_key_mutated<Key, Value, Q: ?Sized>(
687    old_map: Map<Key, Value>,
688    new_map: Map<Key, Value>,
689    key: &Q,
690    old_value: Value,
691    new_value: Value,
692) -> bool {
693    &&& maps_borrowed_key_to_value(old_map, key, old_value)
694    &&& maps_borrowed_key_to_value(new_map, key, new_value)
695    &&& exists|remainder: Map<Key, Value>|
696        {
697            &&& borrowed_key_removed(old_map, remainder, key)
698            &&& borrowed_key_removed(new_map, remainder, key)
699        }
700}
701
702/// Simplifies [`borrowed_key_mutated`] when the borrowed key has the map's key type.
703pub broadcast proof fn lemma_borrowed_key_mutated_deref<Key, Value>(
704    old_map: Map<Key, Value>,
705    new_map: Map<Key, Value>,
706    key: &Key,
707    old_value: Value,
708    new_value: Value,
709)
710    ensures
711        #[trigger] borrowed_key_mutated(old_map, new_map, key, old_value, new_value) <==> {
712            &&& old_map.contains_key(*key)
713            &&& old_map[*key] == old_value
714            &&& new_map == old_map.insert(*key, new_value)
715        },
716{
717    broadcast use {
718        axiom_deref_key_removed,
719        axiom_maps_deref_key_to_value,
720        super::super::map::group_map_lemmas,
721        super::super::set::group_set_lemmas,
722    };
723
724    if borrowed_key_mutated(old_map, new_map, key, old_value, new_value) {
725        let remainder = choose|remainder: Map<Key, Value>|
726            {
727                &&& borrowed_key_removed(old_map, remainder, key)
728                &&& borrowed_key_removed(new_map, remainder, key)
729            };
730        assert(remainder == new_map.remove(*key));
731        assert_maps_equal!(new_map, old_map.insert(*key, new_value), candidate => {
732            if candidate != *key {
733                assert(old_map.remove(*key)[candidate] == old_map[candidate]);
734            }
735        });
736    } else if old_map.contains_key(*key) && old_map[*key] == old_value && new_map == old_map.insert(
737        *key,
738        new_value,
739    ) {
740        let remainder = old_map.remove(*key);
741        assert_maps_equal!(new_map.remove(*key), remainder, candidate => {});
742        assert(borrowed_key_removed(new_map, remainder, key));
743    }
744}
745
746/// Specification for [`BTreeMap::get_mut`].
747pub assume_specification<
748    'a,
749    Key: Borrow<Q> + Ord,
750    Value,
751    A: Allocator + Clone,
752    Q: Ord + ?Sized,
753>[ BTreeMap::<Key, Value, A>::get_mut::<Q> ](
754    map: &'a mut BTreeMap<Key, Value, A>,
755    key: &Q,
756) -> (result: Option<&'a mut Value>)
757    requires
758        borrowed_key_ordering_matches::<Key, Q>(),
759    ensures
760        obeys_cmp::<Key>() ==> match result {
761            Some(value) => borrowed_key_mutated(old(map)@, final(map)@, key, *value, *final(value)),
762            None => !contains_borrowed_key(old(map)@, key) && final(map)@ == old(map)@,
763        },
764;
765
766pub assume_specification<Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::clear ](
767    m: &mut BTreeMap<Key, Value, A>,
768)
769    ensures
770        final(m)@ == Map::<Key, Value>::empty(),
771;
772
773/// Specification for [`BTreeMap::lower_bound_mut`].
774pub assume_specification<
775    'a,
776    Key: Borrow<Q> + Ord,
777    Value,
778    A: Allocator + Clone,
779    Q: Ord + ?Sized,
780>[ BTreeMap::<Key, Value, A>::lower_bound_mut::<Q> ](
781    map: &'a mut BTreeMap<Key, Value, A>,
782    bound: Bound<&Q>,
783) -> (cursor: CursorMut<'a, Key, Value, A>)
784    requires
785        borrowed_key_ordering_matches::<Key, Q>(),
786    ensures
787        obeys_cmp::<Key>() ==> {
788            &&& cursor@.wf()
789            &&& cursor@.map == old(map)@
790            &&& final(map)@ == cursor.final_map()
791            &&& positioned_at_lower_bound(cursor@, bound)
792        },
793;
794
795/// Specification for [`BTreeMap::upper_bound_mut`].
796pub assume_specification<
797    'a,
798    Key: Borrow<Q> + Ord,
799    Value,
800    A: Allocator + Clone,
801    Q: Ord + ?Sized,
802>[ BTreeMap::<Key, Value, A>::upper_bound_mut::<Q> ](
803    map: &'a mut BTreeMap<Key, Value, A>,
804    bound: Bound<&Q>,
805) -> (cursor: CursorMut<'a, Key, Value, A>)
806    requires
807        borrowed_key_ordering_matches::<Key, Q>(),
808    ensures
809        obeys_cmp::<Key>() ==> {
810            &&& cursor@.wf()
811            &&& cursor@.map == old(map)@
812            &&& final(map)@ == cursor.final_map()
813            &&& positioned_at_upper_bound(cursor@, bound)
814        },
815;
816
817/// Specification for [`CursorMut::next`].
818pub assume_specification<'a, 'b, Key, Value, A>[ CursorMut::<'a, Key, Value, A>::next ](
819    cursor: &'b mut CursorMut<'a, Key, Value, A>,
820) -> (result: Option<(&'b Key, &'b mut Value)>)
821    requires
822        old(cursor)@.wf(),
823    ensures
824        final(cursor).final_map() == old(cursor).final_map(),
825        final(cursor)@.wf(),
826        match result {
827            Some((key, value)) => {
828                let old_model = old(cursor)@;
829                let new_model = final(cursor)@;
830                &&& old_model.position < old_model.keys.len()
831                &&& *key == old_model.keys[old_model.position]
832                &&& *value == old_model.map[*key]
833                &&& new_model.keys == old_model.keys
834                &&& new_model.position == old_model.position + 1
835                &&& new_model.map == old_model.map.insert(*key, *final(value))
836            },
837            None => {
838                &&& old(cursor)@.position == old(cursor)@.keys.len()
839                &&& final(cursor)@ == old(cursor)@
840            },
841        },
842;
843
844/// Specification for [`CursorMut::prev`].
845pub assume_specification<'a, 'b, Key, Value, A>[ CursorMut::<'a, Key, Value, A>::prev ](
846    cursor: &'b mut CursorMut<'a, Key, Value, A>,
847) -> (result: Option<(&'b Key, &'b mut Value)>)
848    requires
849        old(cursor)@.wf(),
850    ensures
851        final(cursor).final_map() == old(cursor).final_map(),
852        final(cursor)@.wf(),
853        match result {
854            Some((key, value)) => {
855                let old_model = old(cursor)@;
856                let new_model = final(cursor)@;
857                &&& old_model.position > 0
858                &&& *key == old_model.keys[old_model.position - 1]
859                &&& *value == old_model.map[*key]
860                &&& new_model.keys == old_model.keys
861                &&& new_model.position == old_model.position - 1
862                &&& new_model.map == old_model.map.insert(*key, *final(value))
863            },
864            None => {
865                &&& old(cursor)@.position == 0
866                &&& final(cursor)@ == old(cursor)@
867            },
868        },
869;
870
871/// Specification for [`CursorMut::peek_prev`].
872pub assume_specification<'a, 'b, Key, Value, A>[ CursorMut::<'a, Key, Value, A>::peek_prev ](
873    cursor: &'b mut CursorMut<'a, Key, Value, A>,
874) -> (result: Option<(&'b Key, &'b mut Value)>)
875    requires
876        old(cursor)@.wf(),
877    ensures
878        final(cursor).final_map() == old(cursor).final_map(),
879        final(cursor)@.wf(),
880        match result {
881            Some((key, value)) => {
882                let old_model = old(cursor)@;
883                let new_model = final(cursor)@;
884                &&& old_model.position > 0
885                &&& *key == old_model.keys[old_model.position - 1]
886                &&& *value == old_model.map[*key]
887                &&& new_model.keys == old_model.keys
888                &&& new_model.position == old_model.position
889                &&& new_model.map == old_model.map.insert(*key, *final(value))
890            },
891            None => {
892                &&& old(cursor)@.position == 0
893                &&& final(cursor)@ == old(cursor)@
894            },
895        },
896;
897
898/// Specification for [`CursorMut::peek_next`].
899pub assume_specification<'a, 'b, Key, Value, A>[ CursorMut::<'a, Key, Value, A>::peek_next ](
900    cursor: &'b mut CursorMut<'a, Key, Value, A>,
901) -> (result: Option<(&'b Key, &'b mut Value)>)
902    requires
903        old(cursor)@.wf(),
904    ensures
905        final(cursor).final_map() == old(cursor).final_map(),
906        final(cursor)@.wf(),
907        match result {
908            Some((key, value)) => {
909                let old_model = old(cursor)@;
910                let new_model = final(cursor)@;
911                &&& old_model.position < old_model.keys.len()
912                &&& *key == old_model.keys[old_model.position]
913                &&& *value == old_model.map[*key]
914                &&& new_model.keys == old_model.keys
915                &&& new_model.position == old_model.position
916                &&& new_model.map == old_model.map.insert(*key, *final(value))
917            },
918            None => {
919                &&& old(cursor)@.position == old(cursor)@.keys.len()
920                &&& final(cursor)@ == old(cursor)@
921            },
922        },
923;
924
925/// Specification for [`CursorMut::insert_after`].
926pub assume_specification<'a, Key: Ord, Value, A: Allocator + Clone>[ CursorMut::<
927    'a,
928    Key,
929    Value,
930    A,
931>::insert_after ](cursor: &mut CursorMut<'a, Key, Value, A>, key: Key, value: Value) -> (result:
932    Result<(), UnorderedKeyError>)
933    requires
934        old(cursor)@.wf(),
935    ensures
936        final(cursor).final_map() == old(cursor).final_map(),
937        obeys_cmp::<Key>() ==> {
938            &&& final(cursor)@.wf()
939            &&& match result {
940                Ok(()) => {
941                    let old_model = old(cursor)@;
942                    let new_model = final(cursor)@;
943                    &&& key_fits_at_position(old_model, key)
944                    &&& new_model.keys == old_model.keys.insert(old_model.position, key)
945                    &&& new_model.position == old_model.position
946                    &&& new_model.map == old_model.map.insert(key, value)
947                },
948                Err(_) => {
949                    &&& !key_fits_at_position(old(cursor)@, key)
950                    &&& final(cursor)@ == old(cursor)@
951                },
952            }
953        },
954;
955
956/// Specification for [`CursorMut::remove_next`].
957pub assume_specification<'a, Key: Ord, Value, A: Allocator + Clone>[ CursorMut::<
958    'a,
959    Key,
960    Value,
961    A,
962>::remove_next ](cursor: &mut CursorMut<'a, Key, Value, A>) -> (result: Option<(Key, Value)>)
963    requires
964        old(cursor)@.wf(),
965    ensures
966        final(cursor).final_map() == old(cursor).final_map(),
967        final(cursor)@.wf(),
968        match result {
969            Some((key, value)) => {
970                let old_model = old(cursor)@;
971                let new_model = final(cursor)@;
972                &&& old_model.position < old_model.keys.len()
973                &&& key == old_model.keys[old_model.position]
974                &&& value == old_model.map[key]
975                &&& new_model.keys == old_model.keys.remove(old_model.position)
976                &&& new_model.position == old_model.position
977                &&& new_model.map == old_model.map.remove(key)
978            },
979            None => {
980                &&& old(cursor)@.position == old(cursor)@.keys.len()
981                &&& final(cursor)@ == old(cursor)@
982            },
983        },
984;
985
986pub assume_specification<'a, Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::keys ](
987    m: &'a BTreeMap<Key, Value, A>,
988) -> (keys: Keys<'a, Key, Value>)
989    ensures
990        key_obeys_cmp_spec::<Key>() ==> {
991            &&& IteratorSpec::remaining(&keys).unref().to_set() == m@.dom()
992            &&& IteratorSpec::remaining(&keys).no_duplicates()
993            &&& IteratorSpec::remaining(&keys).len() == m@.dom().len()
994            &&& increasing_seq(IteratorSpec::remaining(&keys))
995            &&& into_iter_keys(keys) == IteratorSpec::remaining(&keys).unref()
996            &&& IteratorSpec::decrease(&keys) is Some
997        },
998;
999
1000pub assume_specification<'a, Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::values ](
1001    m: &'a BTreeMap<Key, Value, A>,
1002) -> (values: Values<'a, Key, Value>)
1003    ensures
1004        key_obeys_cmp_spec::<Key>() ==> {
1005            &&& IteratorSpec::remaining(&values).unref().to_set() == m@.values()
1006            &&& IteratorSpec::remaining(&values).len() == m@.dom().len()
1007            &&& into_iter_values(values) == IteratorSpec::remaining(&values).unref()
1008            &&& IteratorSpec::decrease(&values) is Some
1009            &&& exists|key_seq: Seq<Key>|
1010                {
1011                    &&& increasing_seq(key_seq)
1012                    &&& key_seq.to_set() == m@.dom()
1013                    &&& key_seq.no_duplicates()
1014                    &&& IteratorSpec::remaining(&values) == key_seq.map(|i: int, k| &m@[k])
1015                }
1016        },
1017;
1018
1019pub broadcast axiom fn axiom_btree_map_decreases<Key, Value, A: Allocator + Clone>(
1020    m: BTreeMap<Key, Value, A>,
1021)
1022    ensures
1023        #[trigger] (decreases_to!(m => m@)),
1024;
1025
1026// The `iter` method of a `BTreeSet` returns an iterator of type `btree_set::Iter`,
1027// so we specify that type here.
1028#[verifier::external_type_specification]
1029#[verifier::external_body]
1030#[verifier::accept_recursive_types(K)]
1031pub struct ExSetIter<'a, K: 'a>(btree_set::Iter<'a, K>);
1032
1033// To allow reasoning about the "contents" of the BtreeSet iterator, without using
1034// a prophecy, we need a function that gives us the underlying sequence of the original keys.
1035pub uninterp spec fn into_iter_btree_keys<'a, Key>(i: btree_set::Iter::<'a, Key>) -> Seq<Key>;
1036
1037impl<'a, T> super::iter::IteratorSpecImpl for btree_set::Iter::<'a, T> {
1038    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
1039        true
1040    }
1041
1042    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
1043
1044    uninterp spec fn will_return_none(&self) -> bool;
1045
1046    uninterp spec fn decrease(&self) -> Option<nat>;
1047
1048    open spec fn peek(&self, index: int) -> Option<Self::Item> {
1049        if 0 <= index < into_iter_btree_keys(*self).len() {
1050            Some(&into_iter_btree_keys(*self)[index])
1051        } else {
1052            None
1053        }
1054    }
1055}
1056
1057/// Specifications for the behavior of [`alloc::collections::BTreeSet`](https://doc.rust-lang.org/alloc/collections/struct.BTreeSet.html).
1058///
1059/// We model a `BTreeSet` as having a view of type `Set<Key>`, which reflects the current state of the set.
1060///
1061/// These specifications are only meaningful if `obeys_cmp::<Key>()` hold.
1062/// See [`obeys_cmp`] for information on use with primitive types and custom types.
1063///
1064/// Axioms about the behavior of BTreeSet are present in the broadcast group `vstd::std_specs::btree::group_btree_axioms`.
1065#[verifier::external_type_specification]
1066#[verifier::external_body]
1067#[verifier::accept_recursive_types(Key)]
1068#[verifier::reject_recursive_types(A)]
1069pub struct ExBTreeSet<Key, A: Allocator + Clone>(BTreeSet<Key, A>);
1070
1071impl<Key, A: Allocator + Clone> View for BTreeSet<Key, A> {
1072    type V = Set<Key>;
1073
1074    uninterp spec fn view(&self) -> Set<Key>;
1075}
1076
1077impl<Key: DeepView, A: Allocator + Clone> DeepView for BTreeSet<Key, A> {
1078    type V = Set<Key::V>;
1079
1080    open spec fn deep_view(&self) -> Set<Key::V> {
1081        self@.map(|x: Key| x.deep_view())
1082    }
1083}
1084
1085pub uninterp spec fn spec_btree_set_len<Key, A: Allocator + Clone>(m: &BTreeSet<Key, A>) -> usize;
1086
1087pub broadcast axiom fn axiom_spec_btree_set_len<Key, A: Allocator + Clone>(m: &BTreeSet<Key, A>)
1088    ensures
1089        key_obeys_cmp_spec::<Key>() ==> #[trigger] spec_btree_set_len(m) == m@.len(),
1090;
1091
1092#[verifier::when_used_as_spec(spec_btree_set_len)]
1093pub assume_specification<Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::len ](
1094    m: &BTreeSet<Key, A>,
1095) -> (len: usize)
1096    ensures
1097        len == spec_btree_set_len(m),
1098;
1099
1100pub assume_specification<Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::is_empty ](
1101    m: &BTreeSet<Key, A>,
1102) -> (res: bool)
1103    ensures
1104        res == m@.is_empty(),
1105;
1106
1107pub assume_specification<K: Clone, A: Allocator + Clone>[ <BTreeSet::<K, A> as Clone>::clone ](
1108    this: &BTreeSet<K, A>,
1109) -> (other: BTreeSet<K, A>)
1110    ensures
1111        other@ == this@,
1112;
1113
1114pub assume_specification<Key>[ BTreeSet::<Key>::new ]() -> (m: BTreeSet<Key>)
1115    ensures
1116        m@ == Set::<Key>::empty(),
1117;
1118
1119pub assume_specification<T>[ <BTreeSet<T> as core::default::Default>::default ]() -> (m: BTreeSet<
1120    T,
1121>)
1122    ensures
1123        m@ == Set::<T>::empty(),
1124;
1125
1126pub assume_specification<Key: Ord, A: Allocator + Clone>[ BTreeSet::<Key, A>::insert ](
1127    m: &mut BTreeSet<Key, A>,
1128    k: Key,
1129) -> (result: bool)
1130    ensures
1131        obeys_cmp::<Key>() ==> {
1132            &&& final(m)@ == old(m)@.insert(k)
1133            &&& result == !old(m)@.contains(k)
1134        },
1135;
1136
1137// The specification for `contains` has a parameter `key: &Q`
1138// where you'd expect to find `key: &Key`. This allows for the case
1139// that `Key` can be borrowed as something other than `&Key`. For
1140// instance, `Box<u32>` can be borrowed as `&u32` and `String` can be
1141// borrowed as `&str`, so in those cases `Q` would be `u32` and `str`
1142// respectively.
1143// To deal with this, we have a specification function that opaquely
1144// specifies what it means for a set to contain a borrowed key of type
1145// `&Q`. And the postcondition of `contains` just says that its
1146// result matches the output of that specification function. But this
1147// isn't very helpful by itself, since there's no body to that
1148// specification function. So we have special-case axioms that say
1149// what this means in two important circumstances: (1) `Key = Q` and
1150// (2) `Key = Box<Q>`.
1151pub uninterp spec fn set_contains_borrowed_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q) -> bool;
1152
1153pub broadcast axiom fn axiom_set_contains_deref_key<Q>(m: Set<Q>, k: &Q)
1154    ensures
1155        #[trigger] set_contains_borrowed_key::<Q, Q>(m, k) <==> m.contains(*k),
1156;
1157
1158pub broadcast axiom fn axiom_set_contains_box<Q>(m: Set<Box<Q>>, k: &Q)
1159    ensures
1160        #[trigger] set_contains_borrowed_key::<Box<Q>, Q>(m, k) <==> m.contains(Box::new(*k)),
1161;
1162
1163pub assume_specification<Key: Borrow<Q> + Ord, A: Allocator + Clone, Q: Ord + ?Sized>[ BTreeSet::<
1164    Key,
1165    A,
1166>::contains ](m: &BTreeSet<Key, A>, k: &Q) -> (result: bool)
1167    ensures
1168        obeys_cmp::<Key>() ==> result == set_contains_borrowed_key(m@, k),
1169    no_unwind
1170;
1171
1172// The specification for `get` has a parameter `key: &Q` where you'd
1173// expect to find `key: &Key`. This allows for the case that `Key` can
1174// be borrowed as something other than `&Key`. For instance,
1175// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
1176// as `&str`, so in those cases `Q` would be `u32` and `str`
1177// respectively.
1178// To deal with this, we have a specification function that opaquely
1179// specifies what it means for a returned reference to point to an
1180// element of a BTreeSet. And the postcondition of `get` says that
1181// its result matches the output of that specification function. (It
1182// also says that its result corresponds to the output of
1183// `contains_borrowed_key`, discussed above.) But this isn't very
1184// helpful by itself, since there's no body to that specification
1185// function. So we have special-case axioms that say what this means
1186// in two important circumstances: (1) `Key = Q` and (2) `Key =
1187// Box<Q>`.
1188pub uninterp spec fn sets_borrowed_key_to_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q, v: &Key) -> bool;
1189
1190pub broadcast axiom fn axiom_set_deref_key_to_value<Q>(m: Set<Q>, k: &Q, v: &Q)
1191    ensures
1192        #[trigger] sets_borrowed_key_to_key::<Q, Q>(m, k, v) <==> m.contains(*k) && k == v,
1193;
1194
1195pub broadcast axiom fn axiom_set_box_key_to_value<Q>(m: Set<Box<Q>>, q: &Q, v: &Box<Q>)
1196    ensures
1197        #[trigger] sets_borrowed_key_to_key::<Box<Q>, Q>(m, q, v) <==> (m.contains(*v) && Box::new(
1198            *q,
1199        ) == v),
1200;
1201
1202pub assume_specification<
1203    'a,
1204    Key: Borrow<Q> + Ord,
1205    A: Allocator + Clone,
1206    Q: Ord + ?Sized,
1207>[ BTreeSet::<Key, A>::get::<Q> ](m: &'a BTreeSet<Key, A>, k: &Q) -> (result: Option<&'a Key>)
1208    ensures
1209        obeys_cmp::<Key>() ==> match result {
1210            Some(v) => sets_borrowed_key_to_key(m@, k, v),
1211            None => !set_contains_borrowed_key(m@, k),
1212        },
1213;
1214
1215// The specification for `remove` has a parameter `key: &Q` where
1216// you'd expect to find `key: &Key`. This allows for the case that
1217// `Key` can be borrowed as something other than `&Key`. For instance,
1218// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
1219// as `&str`, so in those cases `Q` would be `u32` and `str`
1220// respectively. To deal with this, we have a specification function
1221// that opaquely specifies what it means for two sets to be related by
1222// a remove of a certain `&Q`. And the postcondition of `remove` says
1223// that `old(self)@` and `self@` satisfy that relationship. (It also
1224// says that its result corresponds to the output of
1225// `set_contains_borrowed_key`, discussed above.) But this isn't very
1226// helpful by itself, since there's no body to that specification
1227// function. So we have special-case axioms that say what this means
1228// in two important circumstances: (1) `Key = Q` and (2) `Key = Box<Q>`.
1229pub uninterp spec fn sets_differ_by_borrowed_key<Key, Q: ?Sized>(
1230    old_m: Set<Key>,
1231    new_m: Set<Key>,
1232    k: &Q,
1233) -> bool;
1234
1235pub broadcast axiom fn axiom_set_deref_key_removed<Q>(old_m: Set<Q>, new_m: Set<Q>, k: &Q)
1236    ensures
1237        #[trigger] sets_differ_by_borrowed_key::<Q, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
1238            *k,
1239        ),
1240;
1241
1242pub broadcast axiom fn axiom_set_box_key_removed<Q>(old_m: Set<Box<Q>>, new_m: Set<Box<Q>>, q: &Q)
1243    ensures
1244        #[trigger] sets_differ_by_borrowed_key::<Box<Q>, Q>(old_m, new_m, q) <==> new_m
1245            == old_m.remove(Box::new(*q)),
1246;
1247
1248pub assume_specification<Key: Borrow<Q> + Ord, A: Allocator + Clone, Q: Ord + ?Sized>[ BTreeSet::<
1249    Key,
1250    A,
1251>::remove::<Q> ](m: &mut BTreeSet<Key, A>, k: &Q) -> (result: bool)
1252    ensures
1253        obeys_cmp::<Key>() ==> {
1254            &&& sets_differ_by_borrowed_key(old(m)@, final(m)@, k)
1255            &&& result == set_contains_borrowed_key(old(m)@, k)
1256        },
1257;
1258
1259pub assume_specification<Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::clear ](
1260    m: &mut BTreeSet<Key, A>,
1261) where A: Clone
1262    ensures
1263        final(m)@ == Set::<Key>::empty(),
1264;
1265
1266pub assume_specification<'a, Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::iter ](
1267    m: &'a BTreeSet<Key, A>,
1268) -> (r: btree_set::Iter<'a, Key>)
1269    ensures
1270        key_obeys_cmp_spec::<Key>() ==> {
1271            &&& IteratorSpec::remaining(&r).unref().to_set() == m@
1272            &&& IteratorSpec::remaining(&r).no_duplicates()
1273            &&& IteratorSpec::remaining(&r).len() == m@.len()
1274            &&& increasing_seq(IteratorSpec::remaining(&r))
1275            &&& into_iter_btree_keys(r) == IteratorSpec::remaining(&r).unref()
1276            &&& IteratorSpec::decrease(&r) is Some
1277        },
1278;
1279
1280pub broadcast axiom fn axiom_btree_set_decreases<Key, A: Allocator + Clone>(m: BTreeSet<Key, A>)
1281    ensures
1282        #[trigger] (decreases_to!(m => m@)),
1283;
1284
1285pub broadcast group group_btree_axioms {
1286    axiom_key_obeys_cmp_spec_meaning,
1287    axiom_increasing_seq_meaning,
1288    axiom_box_key_removed,
1289    axiom_contains_deref_key,
1290    axiom_contains_box,
1291    axiom_deref_key_removed,
1292    axiom_maps_deref_key_to_value,
1293    axiom_maps_box_key_to_value,
1294    axiom_btree_map_deepview_borrow,
1295    axiom_spec_btree_map_len,
1296    axiom_set_box_key_removed,
1297    axiom_set_contains_deref_key,
1298    axiom_set_contains_box,
1299    axiom_set_deref_key_removed,
1300    axiom_set_deref_key_to_value,
1301    axiom_set_box_key_to_value,
1302    axiom_spec_btree_set_len,
1303    axiom_btree_map_decreases,
1304    axiom_btree_set_decreases,
1305    axiom_deref_key_ordering_matches,
1306    axiom_deref_key_cmp,
1307    axiom_has_resolved_cursor,
1308    lemma_borrowed_key_mutated_deref,
1309}
1310
1311} // verus!