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
16use alloc::alloc::Allocator;
17use alloc::boxed::Box;
18use alloc::collections::btree_map;
19use alloc::collections::btree_map::{Keys, Values};
20use alloc::collections::btree_set;
21use alloc::collections::{BTreeMap, BTreeSet};
22use core::borrow::Borrow;
23use core::marker::PhantomData;
24use core::option::Option;
25
26verus! {
27
28/// Whether the `Key` type obeys the cmp spec, required for [`BTreeMap`]
29///
30/// This is a workaround to the fact that [`BTreeMap`] "late binds" the trait bounds when needed.
31/// For instance, [`BTreeMap::iter`] does not require `Key: Ord`, even though it yields ordered
32/// items. Rather, it relies on the fact that [`BTreeMap::insert`] does require `Key: Ord`, meaning
33/// no instance of a [`BTreeMap`] will ever have keys that cannot be comparable.
34///
35/// See also [`axiom_key_obeys_cmp_spec_meaning`].
36pub uninterp spec fn key_obeys_cmp_spec<Key: ?Sized>() -> bool;
37
38/// For types that are ordered, [`key_obeys_cmp_spec`] is equivalent to [`obeys_cmp`].
39pub broadcast axiom fn axiom_key_obeys_cmp_spec_meaning<K: Ord>()
40    ensures
41        #[trigger] key_obeys_cmp_spec::<K>() <==> obeys_cmp::<K>(),
42;
43
44/// Whether a sequence is ordered in increasing order.
45/// This only has meaning if `K: Ord` and [`obeys_cmp::<K>`].
46///
47/// See [`axiom_increasing_seq_meaning`] for an interpretation of this predicate.
48pub uninterp spec fn increasing_seq<K>(s: Seq<K>) -> bool;
49
50/// An interpretation for the [`increasing_seq`] predicate.
51pub broadcast axiom fn axiom_increasing_seq_meaning<K: Ord>(s: Seq<K>)
52    requires
53        obeys_cmp::<K>(),
54    ensures
55        #[trigger] increasing_seq(s) <==> forall|i, j|
56            0 <= i < j < s.len() ==> s[i].cmp_spec(&s[j]) is Less,
57;
58
59/// Specifications for the behavior of
60/// [`alloc::collections::btree_map::Keys`](https://doc.rust-lang.org/alloc/collections/btree_map/struct.Keys.html).
61#[verifier::external_type_specification]
62#[verifier::external_body]
63#[verifier::accept_recursive_types(Key)]
64#[verifier::accept_recursive_types(Value)]
65pub struct ExKeys<'a, Key, Value>(Keys<'a, Key, Value>);
66
67// To allow reasoning about the "contents" of the Keys iterator, without using
68// a prophecy, we need a function that gives us the underlying sequence of the original keys.
69pub uninterp spec fn into_iter_keys<'a, Key, Value>(i: Keys<'a, Key, Value>) -> Seq<Key>;
70
71impl<'a, K, V> super::iter::IteratorSpecImpl for Keys<'a, K, V> {
72    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
73        true
74    }
75
76    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
77
78    uninterp spec fn will_return_none(&self) -> bool;
79
80    #[verifier::prophetic]
81    open spec fn initial_value_relation(&self, init: &Self) -> bool {
82        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
83        &&& into_iter_keys(*self) == IteratorSpec::remaining(self).unref()
84    }
85
86    uninterp spec fn decrease(&self) -> Option<nat>;
87
88    open spec fn peek(&self, index: int) -> Option<Self::Item> {
89        if 0 <= index < into_iter_keys(*self).len() {
90            Some(&into_iter_keys(*self)[index])
91        } else {
92            None
93        }
94    }
95}
96
97/// Specifications for the behavior of
98/// [`alloc::collections::btree_map::Values`](https://doc.rust-lang.org/alloc/collections/btree_map/struct.Values.html).
99#[verifier::external_type_specification]
100#[verifier::external_body]
101#[verifier::accept_recursive_types(Key)]
102#[verifier::accept_recursive_types(Value)]
103pub struct ExValues<'a, Key, Value>(Values<'a, Key, Value>);
104
105// To allow reasoning about the "contents" of the Values iterator, without using
106// a prophecy, we need a function that gives us the underlying sequence of the original values.
107pub uninterp spec fn into_iter_values<'a, Key, Value>(i: Values<'a, Key, Value>) -> Seq<Value>;
108
109impl<'a, K, V> super::iter::IteratorSpecImpl for Values<'a, K, V> {
110    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
111        true
112    }
113
114    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
115
116    uninterp spec fn will_return_none(&self) -> bool;
117
118    #[verifier::prophetic]
119    open spec fn initial_value_relation(&self, init: &Self) -> bool {
120        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
121        &&& into_iter_values(*self) == IteratorSpec::remaining(self).unref()
122    }
123
124    uninterp spec fn decrease(&self) -> Option<nat>;
125
126    open spec fn peek(&self, index: int) -> Option<Self::Item> {
127        if 0 <= index < into_iter_values(*self).len() {
128            Some(&into_iter_values(*self)[index])
129        } else {
130            None
131        }
132    }
133}
134
135// The `iter` method of a `BTreeMap` returns an iterator of type `btree_map::Iter`,
136// so we specify that type here.
137#[verifier::external_type_specification]
138#[verifier::external_body]
139#[verifier::accept_recursive_types(K)]
140#[verifier::accept_recursive_types(V)]
141pub struct ExMapIter<'a, K, V>(btree_map::Iter<'a, K, V>);
142
143// To allow reasoning about the "contents" of the Iter iterator, without using
144// a prophecy, we need a function that gives us the underlying sequence of the original map.
145pub uninterp spec fn into_iter<'a, Key, Value>(i: btree_map::Iter<'a, Key, Value>) -> Seq<
146    (Key, Value),
147>;
148
149impl<'a, K, V> super::iter::IteratorSpecImpl for btree_map::Iter<'a, K, V> {
150    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
151        true
152    }
153
154    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
155
156    uninterp spec fn will_return_none(&self) -> bool;
157
158    #[verifier::prophetic]
159    open spec fn initial_value_relation(&self, init: &Self) -> bool {
160        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
161        &&& into_iter(*self) == IteratorSpec::remaining(self).unref()
162    }
163
164    uninterp spec fn decrease(&self) -> Option<nat>;
165
166    open spec fn peek(&self, index: int) -> Option<Self::Item> {
167        if 0 <= index < into_iter(*self).len() {
168            let (k, v) = into_iter(*self)[index];
169            Some((&k, &v))
170        } else {
171            None
172        }
173    }
174}
175
176// To allow reasoning about the ghost iterator when the executable
177// function `iter()` is invoked in a `for` loop header (e.g., in
178// `for x in it: v.iter() { ... }`), we need to specify the behavior of
179// the iterator in spec mode. To do that, we add
180// `#[verifier::when_used_as_spec(spec_iter)]` to the specification for
181// the executable `iter` method and define that spec function here.
182pub uninterp spec fn spec_btree_map_iter<'a, Key, Value, A: Allocator + Clone>(
183    m: &'a BTreeMap<Key, Value, A>,
184) -> (r: btree_map::Iter<'a, Key, Value>);
185
186pub broadcast axiom fn axiom_spec_btree_map_iter<'a, Key, Value, A: Allocator + Clone>(
187    m: &'a BTreeMap<Key, Value, A>,
188)
189    ensures
190        ({
191            // REVIEW: I'm not sure whether this is the right set of facts/triggers
192            let v = #[trigger] spec_btree_map_iter(m).remaining();
193            &&& v.len() == m@.dom().len()
194            &&& forall|i: int|
195                #![trigger m@.contains_key(*v[i].0)]
196                #![trigger m@[*v[i].0]]
197                0 <= i < v.len() ==> m@.contains_key(*v[i].0) && m@[*v[i].0] == *v[i].1
198            &&& forall|k: Key| #[trigger] m@.contains_key(k) ==> v.contains((&k, &m@[k]))
199            &&& v.unref().to_set() == m@.kv_pairs()
200        }),
201;
202
203#[verifier::when_used_as_spec(spec_btree_map_iter)]
204pub assume_specification<'a, Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::iter ](
205    m: &'a BTreeMap<Key, Value, A>,
206) -> (iter: btree_map::Iter<'a, Key, Value>)
207    ensures
208        key_obeys_cmp_spec::<Key>() ==> {
209            &&& iter == spec_btree_map_iter(m)
210            &&& iter.remaining().no_duplicates()
211            &&& IteratorSpec::decrease(&iter) is Some
212            &&& IteratorSpec::initial_value_relation(&iter, &iter)
213            &&& increasing_seq(iter.remaining().map_values(|kv: (&Key, &Value)| *kv.0))
214        },
215;
216
217/// Specifications for the behavior of [`alloc::collections::BTreeMap`](https://doc.rust-lang.org/alloc/collections/struct.BTreeMap.html).
218///
219/// We model a `BTreeMap` as having a view of type `Map<Key, Value>`, which reflects the current state of the map.
220///
221/// These specifications are only meaningful if `key_obeys_cmp_spec::<Key>()` holds.
222/// See [`key_obeys_cmp_spec`] for information on use with primitive types and other types.
223///
224/// Axioms about the behavior of BTreeMap are present in the broadcast group `vstd::std_specs::btree::group_btree_axioms`.
225#[verifier::external_type_specification]
226#[verifier::external_body]
227#[verifier::accept_recursive_types(Key)]
228#[verifier::accept_recursive_types(Value)]
229#[verifier::reject_recursive_types(A)]
230pub struct ExBTreeMap<Key, Value, A: Allocator + Clone>(BTreeMap<Key, Value, A>);
231
232pub trait BTreeMapAdditionalSpecFns<Key, Value>: View<V = Map<Key, Value>> {
233    spec fn spec_index(&self, k: Key) -> Value
234        recommends
235            self@.contains_key(k),
236    ;
237}
238
239impl<Key, Value, A: Allocator + Clone> BTreeMapAdditionalSpecFns<Key, Value> for BTreeMap<
240    Key,
241    Value,
242    A,
243> {
244    #[verifier::inline]
245    open spec fn spec_index(&self, k: Key) -> Value {
246        self@.index(k)
247    }
248}
249
250impl<Key, Value, A: Allocator + Clone> View for BTreeMap<Key, Value, A> {
251    type V = Map<Key, Value>;
252
253    uninterp spec fn view(&self) -> Map<Key, Value>;
254}
255
256impl<Key: DeepView, Value: DeepView, A: Allocator + Clone> DeepView for BTreeMap<Key, Value, A> {
257    type V = Map<Key::V, Value::V>;
258
259    open spec fn deep_view(&self) -> Map<Key::V, Value::V> {
260        btree_map_deep_view_impl(*self)
261    }
262}
263
264/// The actual definition of `BTreeMap::deep_view`.
265///
266/// This is a separate function since it introduces a lot of quantifiers and revealing an opaque trait
267/// method is not supported. In most cases, it's easier to use one of the lemmas below instead
268/// of revealing this function directly.
269#[verifier::opaque]
270pub open spec fn btree_map_deep_view_impl<Key: DeepView, Value: DeepView, A: Allocator + Clone>(
271    m: BTreeMap<Key, Value, A>,
272) -> Map<Key::V, Value::V> {
273    Map::new(
274        m@.dom().map(|k: Key| k.deep_view()),
275        |dk: Key::V|
276            {
277                let k = choose|k: Key| m@.contains_key(k) && #[trigger] k.deep_view() == dk;
278                m@[k].deep_view()
279            },
280    )
281}
282
283pub broadcast proof fn lemma_btree_map_deepview_dom<K: DeepView, V: DeepView>(m: BTreeMap<K, V>)
284    ensures
285        #[trigger] m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()),
286{
287    reveal(btree_map_deep_view_impl);
288    broadcast use group_btree_axioms;
289    broadcast use crate::vstd::group_vstd_default;
290
291    assert(m.deep_view().dom() =~= m@.dom().map(|k: K| k.deep_view()));
292}
293
294pub broadcast proof fn lemma_btree_map_deepview_properties<K: DeepView, V: DeepView>(
295    m: BTreeMap<K, V>,
296)
297    requires
298        crate::relations::injective(|k: K| k.deep_view()),
299    ensures
300        #![trigger m.deep_view()]
301        // all elements in m.view() are present in m.deep_view()
302        forall|k: K| #[trigger]
303            m@.contains_key(k) ==> m.deep_view().contains_key(k.deep_view())
304                && m.deep_view()[k.deep_view()] == m@[k].deep_view(),
305        // all elements in m.deep_view() are present in m.view()
306        forall|dk: <K as DeepView>::V| #[trigger]
307            m.deep_view().contains_key(dk) ==> exists|k: K|
308                k.deep_view() == dk && #[trigger] m@.contains_key(k),
309{
310    reveal(btree_map_deep_view_impl);
311    broadcast use group_btree_axioms;
312    broadcast use crate::vstd::group_vstd_default;
313
314    assert(m.deep_view().dom() == m@.dom().map(|k: K| k.deep_view()));
315    assert forall|k: K| #[trigger] m@.contains_key(k) implies m.deep_view().contains_key(
316        k.deep_view(),
317    ) && m.deep_view()[k.deep_view()] == m@[k].deep_view() by {
318        assert forall|k1: K, k2: K| #[trigger]
319            k1.deep_view() == #[trigger] k2.deep_view() implies k1 == k2 by {
320            let ghost k_deepview = |k: K| k.deep_view();
321            assert(crate::relations::injective(k_deepview));
322            assert(k_deepview(k1) == k_deepview(k2));
323        }
324    }
325}
326
327pub broadcast proof fn lemma_btree_map_deepview_values<K: DeepView, V: DeepView>(m: BTreeMap<K, V>)
328    requires
329        crate::relations::injective(|k: K| k.deep_view()),
330    ensures
331        #[trigger] m.deep_view().values() =~= m@.values().map(|v: V| v.deep_view()),
332{
333    reveal(btree_map_deep_view_impl);
334    broadcast use group_btree_axioms;
335    broadcast use lemma_btree_map_deepview_properties;
336    broadcast use crate::vstd::group_vstd_default;
337
338    let lhs = m.deep_view().values();
339    let rhs = m@.values().map(|v: V| v.deep_view());
340    assert forall|v: V::V| #[trigger] lhs.contains(v) implies rhs.contains(v) by {
341        let dk = choose|dk: K::V| #[trigger]
342            m.deep_view().contains_key(dk) && m.deep_view()[dk] == v;
343        let k = choose|k: K| #[trigger] m@.contains_key(k) && k.deep_view() == dk;
344        let ov = choose|ov: V| #[trigger] m@.contains_key(k) && m@[k] == ov && ov.deep_view() == v;
345        assert(v == ov.deep_view());
346        assert(m@.values().contains(ov));
347    }
348}
349
350/// Borrowing a key works the same way on deep_view as on view,
351/// if deep_view is injective; see `axiom_contains_deref_key`.
352pub broadcast axiom fn axiom_btree_map_deepview_borrow<
353    K: DeepView + Borrow<Q>,
354    V: DeepView,
355    Q: View<V = <K as DeepView>::V> + Eq + ?Sized,
356>(m: BTreeMap<K, V>, k: &Q)
357    requires
358        key_obeys_cmp_spec::<K>(),
359        crate::relations::injective(|k: K| k.deep_view()),
360    ensures
361        #[trigger] contains_borrowed_key(m@, k) <==> m.deep_view().contains_key(k@),
362;
363
364pub uninterp spec fn spec_btree_map_len<Key, Value, A: Allocator + Clone>(
365    m: &BTreeMap<Key, Value, A>,
366) -> usize;
367
368pub broadcast axiom fn axiom_spec_btree_map_len<Key, Value, A: Allocator + Clone>(
369    m: &BTreeMap<Key, Value, A>,
370)
371    ensures
372        key_obeys_cmp_spec::<Key>() ==> #[trigger] spec_btree_map_len(m) == m@.len(),
373;
374
375#[verifier::when_used_as_spec(spec_btree_map_len)]
376pub assume_specification<Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::len ](
377    m: &BTreeMap<Key, Value, A>,
378) -> (len: usize)
379    ensures
380        len == spec_btree_map_len(m),
381;
382
383pub assume_specification<Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::is_empty ](
384    m: &BTreeMap<Key, Value, A>,
385) -> (res: bool)
386    ensures
387        res == m@.is_empty(),
388;
389
390pub assume_specification<K: Clone, V: Clone, A: Allocator + Clone>[ <BTreeMap::<
391    K,
392    V,
393    A,
394> as Clone>::clone ](this: &BTreeMap<K, V, A>) -> (other: BTreeMap<K, V, A>)
395    ensures
396        other@ == this@,
397;
398
399pub assume_specification<Key, Value>[ BTreeMap::<Key, Value>::new ]() -> (m: BTreeMap<Key, Value>)
400    ensures
401        m@ == Map::<Key, Value>::empty(),
402;
403
404pub assume_specification<K, V>[ <BTreeMap<K, V> as core::default::Default>::default ]() -> (m:
405    BTreeMap<K, V>)
406    ensures
407        m@ == Map::<K, V>::empty(),
408;
409
410pub assume_specification<Key: Ord, Value, A: Allocator + Clone>[ BTreeMap::<
411    Key,
412    Value,
413    A,
414>::insert ](m: &mut BTreeMap<Key, Value, A>, k: Key, v: Value) -> (result: Option<Value>)
415    ensures
416        obeys_cmp::<Key>() ==> {
417            &&& final(m)@ == old(m)@.insert(k, v)
418            &&& match result {
419                Some(v) => old(m)@.contains_key(k) && v == old(m)[k],
420                None => !old(m)@.contains_key(k),
421            }
422        },
423;
424
425// The specification for `contains_key` has a parameter `key: &Q`
426// where you'd expect to find `key: &Key`. This allows for the case
427// that `Key` can be borrowed as something other than `&Key`. For
428// instance, `Box<u32>` can be borrowed as `&u32` and `String` can be
429// borrowed as `&str`, so in those cases `Q` would be `u32` and `str`
430// respectively.
431// To deal with this, we have a specification function that opaquely
432// specifies what it means for a map to contain a borrowed key of type
433// `&Q`. And the postcondition of `contains_key` just says that its
434// result matches the output of that specification function. But this
435// isn't very helpful by itself, since there's no body to that
436// specification function. So we have special-case axioms that say
437// what this means in two important circumstances: (1) `Key = Q` and
438// (2) `Key = Box<Q>`.
439pub uninterp spec fn contains_borrowed_key<Key, Value, Q: ?Sized>(
440    m: Map<Key, Value>,
441    k: &Q,
442) -> bool;
443
444pub broadcast axiom fn axiom_contains_deref_key<Q, Value>(m: Map<Q, Value>, k: &Q)
445    ensures
446        #[trigger] contains_borrowed_key::<Q, Value, Q>(m, k) <==> m.contains_key(*k),
447;
448
449pub broadcast axiom fn axiom_contains_box<Q, Value>(m: Map<Box<Q>, Value>, k: &Q)
450    ensures
451        #[trigger] contains_borrowed_key::<Box<Q>, Value, Q>(m, k) <==> m.contains_key(
452            Box::new(*k),
453        ),
454;
455
456pub assume_specification<
457    Key: Borrow<Q> + Ord,
458    Value,
459    A: Allocator + Clone,
460    Q: Ord + ?Sized,
461>[ BTreeMap::<Key, Value, A>::contains_key::<Q> ](m: &BTreeMap<Key, Value, A>, k: &Q) -> (result:
462    bool)
463    ensures
464        obeys_cmp::<Key>() ==> result == contains_borrowed_key(m@, k),
465;
466
467// The specification for `get` has a parameter `key: &Q` where you'd
468// expect to find `key: &Key`. This allows for the case that `Key` can
469// be borrowed as something other than `&Key`. For instance,
470// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
471// as `&str`, so in those cases `Q` would be `u32` and `str`
472// respectively.
473// To deal with this, we have a specification function that opaquely
474// specifies what it means for a map to map a borrowed key of type
475// `&Q` to a certain value. And the postcondition of `get` says that
476// its result matches the output of that specification function. (It
477// also says that its result corresponds to the output of
478// `contains_borrowed_key`, discussed above.) But this isn't very
479// helpful by itself, since there's no body to that specification
480// function. So we have special-case axioms that say what this means
481// in two important circumstances: (1) `Key = Q` and (2) `Key =
482// Box<Q>`.
483pub uninterp spec fn maps_borrowed_key_to_value<Key, Value, Q: ?Sized>(
484    m: Map<Key, Value>,
485    k: &Q,
486    v: Value,
487) -> bool;
488
489pub broadcast axiom fn axiom_maps_deref_key_to_value<Q, Value>(m: Map<Q, Value>, k: &Q, v: Value)
490    ensures
491        #[trigger] maps_borrowed_key_to_value::<Q, Value, Q>(m, k, v) <==> m.contains_key(*k)
492            && m[*k] == v,
493;
494
495pub broadcast axiom fn axiom_maps_box_key_to_value<Q, Value>(m: Map<Box<Q>, Value>, q: &Q, v: Value)
496    ensures
497        #[trigger] maps_borrowed_key_to_value::<Box<Q>, Value, Q>(m, q, v) <==> {
498            let k = Box::new(*q);
499            &&& m.contains_key(k)
500            &&& m[k] == v
501        },
502;
503
504pub assume_specification<
505    'a,
506    Key: Borrow<Q> + Ord,
507    Value,
508    A: Allocator + Clone,
509    Q: Ord + ?Sized,
510>[ BTreeMap::<Key, Value, A>::get::<Q> ](m: &'a BTreeMap<Key, Value, A>, k: &Q) -> (result: Option<
511    &'a Value,
512>)
513    ensures
514        obeys_cmp::<Key>() ==> match result {
515            Some(v) => maps_borrowed_key_to_value(m@, k, *v),
516            None => !contains_borrowed_key(m@, k),
517        },
518;
519
520// The specification for `remove` has a parameter `key: &Q` where
521// you'd expect to find `key: &Key`. This allows for the case that
522// `Key` can be borrowed as something other than `&Key`. For instance,
523// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
524// as `&str`, so in those cases `Q` would be `u32` and `str`
525// respectively. To deal with this, we have a specification function
526// that opaquely specifies what it means for two maps to be related by
527// a remove of a certain `&Q`. And the postcondition of `remove` says
528// that `old(self)@` and `self@` satisfy that relationship. (It also
529// says that its result corresponds to the output of
530// `contains_borrowed_key` and `maps_borrowed_key_to_value`, discussed
531// above.) But this isn't very helpful by itself, since there's no
532// body to that specification function. So we have special-case axioms
533// that say what this means in two important circumstances: (1) `Key =
534// Q` and (2) `Key = Box<Q>`.
535pub uninterp spec fn borrowed_key_removed<Key, Value, Q: ?Sized>(
536    old_m: Map<Key, Value>,
537    new_m: Map<Key, Value>,
538    k: &Q,
539) -> bool;
540
541pub broadcast axiom fn axiom_deref_key_removed<Q, Value>(
542    old_m: Map<Q, Value>,
543    new_m: Map<Q, Value>,
544    k: &Q,
545)
546    ensures
547        #[trigger] borrowed_key_removed::<Q, Value, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
548            *k,
549        ),
550;
551
552pub broadcast axiom fn axiom_box_key_removed<Q, Value>(
553    old_m: Map<Box<Q>, Value>,
554    new_m: Map<Box<Q>, Value>,
555    q: &Q,
556)
557    ensures
558        #[trigger] borrowed_key_removed::<Box<Q>, Value, Q>(old_m, new_m, q) <==> new_m
559            == old_m.remove(Box::new(*q)),
560;
561
562pub assume_specification<
563    Key: Borrow<Q> + Ord,
564    Value,
565    A: Allocator + Clone,
566    Q: Ord + ?Sized,
567>[ BTreeMap::<Key, Value, A>::remove::<Q> ](m: &mut BTreeMap<Key, Value, A>, k: &Q) -> (result:
568    Option<Value>)
569    ensures
570        obeys_cmp::<Key>() ==> {
571            &&& borrowed_key_removed(old(m)@, final(m)@, k)
572            &&& match result {
573                Some(v) => maps_borrowed_key_to_value(old(m)@, k, v),
574                None => !contains_borrowed_key(old(m)@, k),
575            }
576        },
577;
578
579pub assume_specification<Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::clear ](
580    m: &mut BTreeMap<Key, Value, A>,
581)
582    ensures
583        final(m)@ == Map::<Key, Value>::empty(),
584;
585
586// To allow reasoning about the ghost Keys iterator when the executable
587// function `keys()` is invoked in a `for` loop header (e.g., in
588// `for x in it: m.keys() { ... }`), we need to specify the behavior of
589// the iterator in spec mode. To do that, we add
590// `#[verifier::when_used_as_spec(spec_iter)` to the specification for
591// the executable `iter` method and define that spec function here.
592pub uninterp spec fn spec_keys_iter<'a, Key, Value, A: Allocator + Clone>(
593    m: &'a BTreeMap<Key, Value, A>,
594) -> (keys: Keys<'a, Key, Value>);
595
596pub broadcast proof fn axiom_spec_keys_iter<'a, Key, Value, A: Allocator + Clone>(
597    m: &'a BTreeMap<Key, Value, A>,
598)
599    ensures
600        (#[trigger] spec_keys_iter(m).remaining()).unref().to_set() == m@.dom(),
601        spec_keys_iter(m).remaining().no_duplicates(),
602        spec_keys_iter(m).remaining().len() == m@.dom().len(),
603        increasing_seq(spec_keys_iter(m).remaining()),
604{
605    admit();
606}
607
608#[verifier::when_used_as_spec(spec_keys_iter)]
609pub assume_specification<'a, Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::keys ](
610    m: &'a BTreeMap<Key, Value, A>,
611) -> (keys: Keys<'a, Key, Value>)
612    ensures
613        key_obeys_cmp_spec::<Key>() ==> {
614            &&& keys == spec_keys_iter(m)
615            &&& IteratorSpec::decrease(&keys) is Some
616            &&& IteratorSpec::initial_value_relation(&keys, &keys)
617        },
618;
619
620// To allow reasoning about the ghost Values iterator when the executable
621// function `value()` is invoked in a `for` loop header (e.g., in
622// `for x in it: m.keys() { ... }`), we need to specify the behavior of
623// the iterator in spec mode. To do that, we add
624// `#[verifier::when_used_as_spec(spec_iter)` to the specification for
625// the executable `iter` method and define that spec function here.
626pub uninterp spec fn spec_values_iter<'a, Key, Value, A: Allocator + Clone>(
627    m: &'a BTreeMap<Key, Value, A>,
628) -> (values: Values<'a, Key, Value>);
629
630pub broadcast proof fn axiom_spec_values_iter<'a, Key, Value, A: Allocator + Clone>(
631    m: &'a BTreeMap<Key, Value, A>,
632)
633    ensures
634        (#[trigger] spec_values_iter(m).remaining()).unref().to_set() == m@.values(),
635        spec_values_iter(m).remaining().len() == m@.dom().len(),
636{
637    admit();
638}
639
640#[verifier::when_used_as_spec(spec_values_iter)]
641pub assume_specification<'a, Key, Value, A: Allocator + Clone>[ BTreeMap::<Key, Value, A>::values ](
642    m: &'a BTreeMap<Key, Value, A>,
643) -> (values: Values<'a, Key, Value>)
644    ensures
645        key_obeys_cmp_spec::<Key>() ==> {
646            &&& values == spec_values_iter(m)
647            &&& IteratorSpec::decrease(&values) is Some
648            &&& IteratorSpec::initial_value_relation(&values, &values)
649            &&& exists|key_seq: Seq<Key>|
650                {
651                    &&& increasing_seq(key_seq)
652                    &&& key_seq.to_set() == m@.dom()
653                    &&& key_seq.no_duplicates()
654                    &&& IteratorSpec::remaining(&values) == key_seq.map(|i: int, k| &m@[k])
655                }
656        },
657;
658
659pub broadcast axiom fn axiom_btree_map_decreases<Key, Value, A: Allocator + Clone>(
660    m: BTreeMap<Key, Value, A>,
661)
662    ensures
663        #[trigger] (decreases_to!(m => m@)),
664;
665
666// The `iter` method of a `BTreeSet` returns an iterator of type `btree_set::Iter`,
667// so we specify that type here.
668#[verifier::external_type_specification]
669#[verifier::external_body]
670#[verifier::accept_recursive_types(K)]
671pub struct ExSetIter<'a, K: 'a>(btree_set::Iter<'a, K>);
672
673// To allow reasoning about the "contents" of the BtreeSet iterator, without using
674// a prophecy, we need a function that gives us the underlying sequence of the original keys.
675pub uninterp spec fn into_iter_btree_keys<'a, Key>(i: btree_set::Iter::<'a, Key>) -> Seq<Key>;
676
677impl<'a, T> super::iter::IteratorSpecImpl for btree_set::Iter::<'a, T> {
678    open spec fn obeys_prophetic_iter_laws(&self) -> bool {
679        true
680    }
681
682    uninterp spec fn remaining(&self) -> Seq<Self::Item>;
683
684    uninterp spec fn will_return_none(&self) -> bool;
685
686    #[verifier::prophetic]
687    open spec fn initial_value_relation(&self, init: &Self) -> bool {
688        &&& IteratorSpec::remaining(init) == IteratorSpec::remaining(self)
689        &&& into_iter_btree_keys(*self) == IteratorSpec::remaining(self).unref()
690    }
691
692    uninterp spec fn decrease(&self) -> Option<nat>;
693
694    open spec fn peek(&self, index: int) -> Option<Self::Item> {
695        if 0 <= index < into_iter_btree_keys(*self).len() {
696            Some(&into_iter_btree_keys(*self)[index])
697        } else {
698            None
699        }
700    }
701}
702
703/// Specifications for the behavior of [`alloc::collections::BTreeSet`](https://doc.rust-lang.org/alloc/collections/struct.BTreeSet.html).
704///
705/// We model a `BTreeSet` as having a view of type `Set<Key>`, which reflects the current state of the set.
706///
707/// These specifications are only meaningful if `obeys_cmp::<Key>()` hold.
708/// See [`obeys_cmp`] for information on use with primitive types and custom types.
709///
710/// Axioms about the behavior of BTreeSet are present in the broadcast group `vstd::std_specs::btree::group_btree_axioms`.
711#[verifier::external_type_specification]
712#[verifier::external_body]
713#[verifier::accept_recursive_types(Key)]
714#[verifier::reject_recursive_types(A)]
715pub struct ExBTreeSet<Key, A: Allocator + Clone>(BTreeSet<Key, A>);
716
717impl<Key, A: Allocator + Clone> View for BTreeSet<Key, A> {
718    type V = Set<Key>;
719
720    uninterp spec fn view(&self) -> Set<Key>;
721}
722
723impl<Key: DeepView, A: Allocator + Clone> DeepView for BTreeSet<Key, A> {
724    type V = Set<Key::V>;
725
726    open spec fn deep_view(&self) -> Set<Key::V> {
727        self@.map(|x: Key| x.deep_view())
728    }
729}
730
731pub uninterp spec fn spec_btree_set_len<Key, A: Allocator + Clone>(m: &BTreeSet<Key, A>) -> usize;
732
733pub broadcast axiom fn axiom_spec_btree_set_len<Key, A: Allocator + Clone>(m: &BTreeSet<Key, A>)
734    ensures
735        key_obeys_cmp_spec::<Key>() ==> #[trigger] spec_btree_set_len(m) == m@.len(),
736;
737
738#[verifier::when_used_as_spec(spec_btree_set_len)]
739pub assume_specification<Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::len ](
740    m: &BTreeSet<Key, A>,
741) -> (len: usize)
742    ensures
743        len == spec_btree_set_len(m),
744;
745
746pub assume_specification<Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::is_empty ](
747    m: &BTreeSet<Key, A>,
748) -> (res: bool)
749    ensures
750        res == m@.is_empty(),
751;
752
753pub assume_specification<K: Clone, A: Allocator + Clone>[ <BTreeSet::<K, A> as Clone>::clone ](
754    this: &BTreeSet<K, A>,
755) -> (other: BTreeSet<K, A>)
756    ensures
757        other@ == this@,
758;
759
760pub assume_specification<Key>[ BTreeSet::<Key>::new ]() -> (m: BTreeSet<Key>)
761    ensures
762        m@ == Set::<Key>::empty(),
763;
764
765pub assume_specification<T>[ <BTreeSet<T> as core::default::Default>::default ]() -> (m: BTreeSet<
766    T,
767>)
768    ensures
769        m@ == Set::<T>::empty(),
770;
771
772pub assume_specification<Key: Ord, A: Allocator + Clone>[ BTreeSet::<Key, A>::insert ](
773    m: &mut BTreeSet<Key, A>,
774    k: Key,
775) -> (result: bool)
776    ensures
777        obeys_cmp::<Key>() ==> {
778            &&& final(m)@ == old(m)@.insert(k)
779            &&& result == !old(m)@.contains(k)
780        },
781;
782
783// The specification for `contains` has a parameter `key: &Q`
784// where you'd expect to find `key: &Key`. This allows for the case
785// that `Key` can be borrowed as something other than `&Key`. For
786// instance, `Box<u32>` can be borrowed as `&u32` and `String` can be
787// borrowed as `&str`, so in those cases `Q` would be `u32` and `str`
788// respectively.
789// To deal with this, we have a specification function that opaquely
790// specifies what it means for a set to contain a borrowed key of type
791// `&Q`. And the postcondition of `contains` just says that its
792// result matches the output of that specification function. But this
793// isn't very helpful by itself, since there's no body to that
794// specification function. So we have special-case axioms that say
795// what this means in two important circumstances: (1) `Key = Q` and
796// (2) `Key = Box<Q>`.
797pub uninterp spec fn set_contains_borrowed_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q) -> bool;
798
799pub broadcast axiom fn axiom_set_contains_deref_key<Q>(m: Set<Q>, k: &Q)
800    ensures
801        #[trigger] set_contains_borrowed_key::<Q, Q>(m, k) <==> m.contains(*k),
802;
803
804pub broadcast axiom fn axiom_set_contains_box<Q>(m: Set<Box<Q>>, k: &Q)
805    ensures
806        #[trigger] set_contains_borrowed_key::<Box<Q>, Q>(m, k) <==> m.contains(Box::new(*k)),
807;
808
809pub assume_specification<Key: Borrow<Q> + Ord, A: Allocator + Clone, Q: Ord + ?Sized>[ BTreeSet::<
810    Key,
811    A,
812>::contains ](m: &BTreeSet<Key, A>, k: &Q) -> (result: bool)
813    ensures
814        obeys_cmp::<Key>() ==> result == set_contains_borrowed_key(m@, k),
815;
816
817// The specification for `get` has a parameter `key: &Q` where you'd
818// expect to find `key: &Key`. This allows for the case that `Key` can
819// be borrowed as something other than `&Key`. For instance,
820// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
821// as `&str`, so in those cases `Q` would be `u32` and `str`
822// respectively.
823// To deal with this, we have a specification function that opaquely
824// specifies what it means for a returned reference to point to an
825// element of a BTreeSet. And the postcondition of `get` says that
826// its result matches the output of that specification function. (It
827// also says that its result corresponds to the output of
828// `contains_borrowed_key`, discussed above.) But this isn't very
829// helpful by itself, since there's no body to that specification
830// function. So we have special-case axioms that say what this means
831// in two important circumstances: (1) `Key = Q` and (2) `Key =
832// Box<Q>`.
833pub uninterp spec fn sets_borrowed_key_to_key<Key, Q: ?Sized>(m: Set<Key>, k: &Q, v: &Key) -> bool;
834
835pub broadcast axiom fn axiom_set_deref_key_to_value<Q>(m: Set<Q>, k: &Q, v: &Q)
836    ensures
837        #[trigger] sets_borrowed_key_to_key::<Q, Q>(m, k, v) <==> m.contains(*k) && k == v,
838;
839
840pub broadcast axiom fn axiom_set_box_key_to_value<Q>(m: Set<Box<Q>>, q: &Q, v: &Box<Q>)
841    ensures
842        #[trigger] sets_borrowed_key_to_key::<Box<Q>, Q>(m, q, v) <==> (m.contains(*v) && Box::new(
843            *q,
844        ) == v),
845;
846
847pub assume_specification<
848    'a,
849    Key: Borrow<Q> + Ord,
850    A: Allocator + Clone,
851    Q: Ord + ?Sized,
852>[ BTreeSet::<Key, A>::get::<Q> ](m: &'a BTreeSet<Key, A>, k: &Q) -> (result: Option<&'a Key>)
853    ensures
854        obeys_cmp::<Key>() ==> match result {
855            Some(v) => sets_borrowed_key_to_key(m@, k, v),
856            None => !set_contains_borrowed_key(m@, k),
857        },
858;
859
860// The specification for `remove` has a parameter `key: &Q` where
861// you'd expect to find `key: &Key`. This allows for the case that
862// `Key` can be borrowed as something other than `&Key`. For instance,
863// `Box<u32>` can be borrowed as `&u32` and `String` can be borrowed
864// as `&str`, so in those cases `Q` would be `u32` and `str`
865// respectively. To deal with this, we have a specification function
866// that opaquely specifies what it means for two sets to be related by
867// a remove of a certain `&Q`. And the postcondition of `remove` says
868// that `old(self)@` and `self@` satisfy that relationship. (It also
869// says that its result corresponds to the output of
870// `set_contains_borrowed_key`, discussed above.) But this isn't very
871// helpful by itself, since there's no body to that specification
872// function. So we have special-case axioms that say what this means
873// in two important circumstances: (1) `Key = Q` and (2) `Key = Box<Q>`.
874pub uninterp spec fn sets_differ_by_borrowed_key<Key, Q: ?Sized>(
875    old_m: Set<Key>,
876    new_m: Set<Key>,
877    k: &Q,
878) -> bool;
879
880pub broadcast axiom fn axiom_set_deref_key_removed<Q>(old_m: Set<Q>, new_m: Set<Q>, k: &Q)
881    ensures
882        #[trigger] sets_differ_by_borrowed_key::<Q, Q>(old_m, new_m, k) <==> new_m == old_m.remove(
883            *k,
884        ),
885;
886
887pub broadcast axiom fn axiom_set_box_key_removed<Q>(old_m: Set<Box<Q>>, new_m: Set<Box<Q>>, q: &Q)
888    ensures
889        #[trigger] sets_differ_by_borrowed_key::<Box<Q>, Q>(old_m, new_m, q) <==> new_m
890            == old_m.remove(Box::new(*q)),
891;
892
893pub assume_specification<Key: Borrow<Q> + Ord, A: Allocator + Clone, Q: Ord + ?Sized>[ BTreeSet::<
894    Key,
895    A,
896>::remove::<Q> ](m: &mut BTreeSet<Key, A>, k: &Q) -> (result: bool)
897    ensures
898        obeys_cmp::<Key>() ==> {
899            &&& sets_differ_by_borrowed_key(old(m)@, final(m)@, k)
900            &&& result == set_contains_borrowed_key(old(m)@, k)
901        },
902;
903
904pub assume_specification<Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::clear ](
905    m: &mut BTreeSet<Key, A>,
906) where A: Clone
907    ensures
908        final(m)@ == Set::<Key>::empty(),
909;
910
911// To allow reasoning about the ghost keys in the BtreeSet iterator when the executable
912// function `iter()` is invoked in a `for` loop header (e.g., in
913// `for x in it: m.keys() { ... }`), we need to specify the behavior of
914// the iterator in spec mode. To do that, we add
915// `#[verifier::when_used_as_spec(spec_iter)` to the specification for
916// the executable `iter` method and define that spec function here.
917pub uninterp spec fn spec_btree_keys_iter<'a, Key, A: Allocator + Clone>(
918    m: &'a BTreeSet<Key, A>,
919) -> (r: btree_set::Iter<'a, Key>);
920
921pub broadcast proof fn axiom_spec_btree_keys_iter<'a, Key, A: Allocator + Clone>(
922    m: &'a BTreeSet<Key, A>,
923)
924    ensures
925        (#[trigger] spec_btree_keys_iter(m).remaining()).unref().to_set() == m@,
926        spec_btree_keys_iter(m).remaining().no_duplicates(),
927        spec_btree_keys_iter(m).remaining().len() == m@.len(),
928        increasing_seq(spec_btree_keys_iter(m).remaining()),
929{
930    admit();
931}
932
933#[verifier::when_used_as_spec(spec_btree_keys_iter)]
934pub assume_specification<'a, Key, A: Allocator + Clone>[ BTreeSet::<Key, A>::iter ](
935    m: &'a BTreeSet<Key, A>,
936) -> (r: btree_set::Iter<'a, Key>)
937    ensures
938        key_obeys_cmp_spec::<Key>() ==> {
939            &&& r == spec_btree_keys_iter(m)
940            &&& IteratorSpec::decrease(&r) is Some
941            &&& IteratorSpec::initial_value_relation(&r, &r)
942        },
943;
944
945pub broadcast axiom fn axiom_btree_set_decreases<Key, A: Allocator + Clone>(m: BTreeSet<Key, A>)
946    ensures
947        #[trigger] (decreases_to!(m => m@)),
948;
949
950pub broadcast group group_btree_axioms {
951    axiom_key_obeys_cmp_spec_meaning,
952    axiom_increasing_seq_meaning,
953    axiom_box_key_removed,
954    axiom_contains_deref_key,
955    axiom_contains_box,
956    axiom_deref_key_removed,
957    axiom_maps_deref_key_to_value,
958    axiom_maps_box_key_to_value,
959    axiom_btree_map_deepview_borrow,
960    axiom_spec_btree_map_len,
961    axiom_set_box_key_removed,
962    axiom_set_contains_deref_key,
963    axiom_set_contains_box,
964    axiom_set_deref_key_removed,
965    axiom_set_deref_key_to_value,
966    axiom_set_box_key_to_value,
967    axiom_spec_btree_set_len,
968    axiom_spec_btree_keys_iter,
969    axiom_spec_btree_map_iter,
970    axiom_spec_keys_iter,
971    axiom_spec_values_iter,
972    axiom_btree_map_decreases,
973    axiom_btree_set_decreases,
974}
975
976} // verus!