Skip to main content

vstd/
tokens.rs

1use super::multiset::*;
2use super::prelude::*;
3use core::marker::PhantomData;
4
5use verus as verus_;
6verus_! {
7
8// Note that the tokenized_state_machine! macro creates trusted implementations
9// of all these traits. Therefore all the proof functions in here are trusted.
10// The 'collection types', (MapToken, SetToken, MultisetToken) are verified, but the properties
11// of these types is still assumed by the Verus macro, so they're still mostly trusted.
12
13#[verusfmt::skip]
14broadcast use {
15    super::iset::group_iset_lemmas,
16    super::iset_lib::group_iset_lib_default,
17    super::imap::group_imap_lemmas,
18    super::map::group_map_lemmas,
19    super::set::group_set_lemmas,
20    super::set_lib::group_set_lib_default,
21};
22
23/// Unique identifier for every VerusSync instance.
24/// Every "Token" and "Instance" object has an `InstanceId`. These ID values must agree
25/// to perform any token operation.
26pub type InstanceId = super::resource::Loc;
27
28/// Interface for VerusSync tokens created for a field marked with the
29/// `variable`, `option` or `persistent_option` strategies.
30///
31/// | VerusSync Strategy  | Field type  | Token trait            |
32/// |---------------------|-------------|------------------------|
33/// | `variable`          | `V`         | [`UniqueValueToken<V>`](`UniqueValueToken`)        |
34/// | `option`            | `Option<V>` | [`UniqueValueToken<V>`](`UniqueValueToken`)        |
35/// | `persistent_option` | `Option<V>` | `ValueToken<V> + Copy` |
36///
37/// For the cases where the tokens are not `Copy`, then token is necessarily _unique_
38/// per-instance; the sub-trait, [`UniqueValueToken<V>`](`UniqueValueToken`), provides
39/// an additional lemma to prove uniqueness.
40
41pub trait ValueToken<Value> : Sized {
42    spec fn instance_id(&self) -> InstanceId;
43    spec fn value(&self) -> Value;
44
45    /// All tokens (for the same instance) must agree on the value.
46    proof fn agree(tracked &self, tracked other: &Self)
47        requires self.instance_id() == other.instance_id(),
48        ensures self.value() == other.value();
49
50    /// Return an arbitrary token. It's not possible to do anything interesting
51    /// with this token because it doesn't have a specified instance.
52    proof fn arbitrary() -> (tracked s: Self);
53}
54
55/// Interface for VerusSync tokens created for a field marked with the `variable` or `option` strategies.
56///
57/// See the super-trait [`ValueToken`](ValueToken) for more information.
58pub trait UniqueValueToken<Value> : ValueToken<Value> {
59    /// The token for a given instance must be unique; in other words, if we have two
60    /// tokens, they must be for distinct instances.
61    /// Though the first argument is mutable, the value is not really mutated;
62    /// this is only used to ensure unique ownership of the argument.
63    proof fn unique(tracked &mut self, tracked other: &Self)
64        ensures
65            final(self).instance_id() != other.instance_id(),
66            *final(self) == *old(self);
67}
68
69/// Interface for VerusSync tokens created for a field marked with the
70/// `map` or `persistent_map` strategies.
71///
72/// | VerusSync Strategy  | Field type   | Token trait            |
73/// |---------------------|--------------|------------------------|
74/// | `map`               | `Map<K, V> ` | [`UniqueKeyValueToken<K, V>`](`UniqueKeyValueToken`) |
75/// | `imap`              | `IMap<K, V>` | [`UniqueKeyValueToken<K, V>`](`UniqueKeyValueToken`) |
76/// | `persistent_map`    | `Map<K, V>`  | `KeyValueToken<V> + Copy` |
77/// | `persistent_imap`   | `IMap<K, V>` | `KeyValueToken<V> + Copy` |
78///
79/// For the cases where the tokens are not `Copy`, then token is necessarily _unique_
80/// per-instance, per-key; the sub-trait, [`UniqueKeyValueToken<V>`](`UniqueKeyValueToken`), provides
81/// an additional lemma to prove uniqueness.
82///
83/// Each token represents a _single_ key-value pair.
84/// To work with a collection of `KeyValueToken`s, use [`MapToken`].
85
86pub trait KeyValueToken<Key, Value> : Sized {
87    spec fn instance_id(&self) -> InstanceId;
88    spec fn key(&self) -> Key;
89    spec fn value(&self) -> Value;
90
91    /// All tokens, for the same instance and _key_, must agree on the value.
92    proof fn agree(tracked &self, tracked other: &Self)
93        requires self.instance_id() == other.instance_id(),
94                 self.key() == other.key(),
95        ensures self.value() == other.value();
96
97    /// Return an arbitrary token. It's not possible to do anything interesting
98    /// with this token because it doesn't have a specified instance.
99    proof fn arbitrary() -> (tracked s: Self);
100}
101
102/// Interface for VerusSync tokens created for a field marked with the `map` strategy.
103///
104/// See the super-trait [`KeyValueToken`](KeyValueToken) for more information.
105pub trait UniqueKeyValueToken<Key, Value> : KeyValueToken<Key, Value> {
106    /// The token for a given instance and key must be unique; in other words, if we have two
107    /// tokens, they must be for distinct instances or keys.
108    /// Though the first argument is mutable, the value is not really mutated;
109    /// this is only used to ensure unique ownership of the argument.
110    proof fn unique(tracked &mut self, tracked other: &Self)
111        ensures
112            final(self).instance_id() != other.instance_id() || final(self).key() != other.key(),
113            *final(self) == *old(self);
114}
115
116/// Interface for VerusSync tokens created for a field marked with the `count` strategy.
117///
118/// | VerusSync Strategy  | Field type  | Token trait            |
119/// |---------------------|-------------|------------------------|
120/// | `count`             | `nat`       | `CountToken`           |
121///
122/// These tokens are "fungible" in the sense that they can be combined and split, numbers
123/// combining additively.
124///
125/// (For the `persistent_count` strategy, see [`MonotonicCountToken`].)
126pub trait CountToken : Sized {
127    spec fn instance_id(&self) -> InstanceId;
128    spec fn count(&self) -> nat;
129
130    proof fn join(tracked &mut self, tracked other: Self)
131        requires
132            old(self).instance_id() == other.instance_id(),
133        ensures
134            final(self).instance_id() == old(self).instance_id(),
135            final(self).count() == old(self).count() + other.count();
136
137    proof fn split(tracked &mut self, count: nat) -> (tracked token: Self)
138        requires
139            count <= old(self).count()
140        ensures
141            final(self).instance_id() == old(self).instance_id(),
142            final(self).count() == old(self).count() - count,
143            token.instance_id() == old(self).instance_id(),
144            token.count() == count;
145
146    proof fn weaken_shared(tracked &self, count: nat) -> (tracked s: &Self)
147        requires count <= self.count(),
148        ensures s.instance_id() == self.instance_id(),
149            s.count() == count;
150
151    /// Return an arbitrary token. It's not possible to do anything interesting
152    /// with this token because it doesn't have a specified instance.
153    proof fn arbitrary() -> (tracked s: Self);
154}
155
156/// Interface for VerusSync tokens created for a field marked with the `persistent_count` strategy.
157///
158/// | VerusSync Strategy  | Field type  | Token trait                   |
159/// |---------------------|-------------|-------------------------------|
160/// | `persistent_count`  | `nat`       | `MonotonicCountToken + Copy`  |
161///
162/// A token represents a "lower bound" on the field value, which increases monotonically.
163
164pub trait MonotonicCountToken : Sized {
165    spec fn instance_id(&self) -> InstanceId;
166    spec fn count(&self) -> nat;
167
168    proof fn weaken(tracked &self, count: nat) -> (tracked s: Self)
169        requires count <= self.count(),
170        ensures s.instance_id() == self.instance_id(),
171            s.count() == count;
172
173    /// Return an arbitrary token. It's not possible to do anything interesting
174    /// with this token because it doesn't have a specified instance.
175    proof fn arbitrary() -> (tracked s: Self);
176}
177
178/// Interface for VerusSync tokens created for a field marked with the
179/// `set`, `persistent_set` or `multiset` strategies.
180///
181/// | VerusSync Strategy  | Field type   | Token trait            |
182/// |---------------------|--------------|------------------------|
183/// | `set`               | `Set<V>`     | [`UniqueElementToken<V>`](`UniqueElementToken`) |
184/// | `iset`              | `ISet<V>`    | [`UniqueElementToken<V>`](`UniqueElementToken`) |
185/// | `persistent_set`    | `Set<V>`     | `ElementToken<V> + Copy` |
186/// | `persistent_iset`   | `ISet<V>`    | `ElementToken<V> + Copy` |
187/// | `multiset`          | `Multiset<V>` | `ElementToken<V>`      |
188///
189/// Each token represents a single element of the set or multiset.
190///
191///  * For the `set` strategy, the token for any given element is unique.
192///  * For the `persistent_set` strategy, the token for any given element is not unique, but is `Copy`.
193///  * For the `multiset` strategy, the tokens are neither unique nor `Copy`, as the specific
194///    multiplicity of each element must be exact.
195///
196/// To work with a collection of `ElementToken`s, use [`SetToken`] or [`MultisetToken`].
197
198pub trait ElementToken<Element> : Sized {
199    spec fn instance_id(&self) -> InstanceId;
200    spec fn element(&self) -> Element;
201
202    /// Return an arbitrary token. It's not possible to do anything interesting
203    /// with this token because it doesn't have a specified instance.
204    proof fn arbitrary() -> (tracked s: Self);
205}
206
207/// Interface for VerusSync tokens created for a field marked with the `set` strategy.
208///
209/// See the super-trait [`ElementToken`](ElementToken) for more information.
210pub trait UniqueElementToken<Element> : ElementToken<Element> {
211    /// The token for a given instance and element must be unique; in other words, if we have two
212    /// tokens, they must be for distinct instances or elements.
213    /// Though the first argument is mutable, the value is not really mutated;
214    /// this is only used to ensure unique ownership of the argument.
215    proof fn unique(tracked &mut self, tracked other: &Self)
216        ensures
217            final(self).instance_id() == other.instance_id() ==> final(self).element() != other.element(),
218            *final(self) == *old(self);
219}
220
221/// Interface for VerusSync tokens created for a field marked with the `bool` or
222/// `persistent_bool` strategy.
223///
224/// | VerusSync Strategy  | Field type  | Token trait            |
225/// |---------------------|-------------|------------------------|
226/// | `bool`              | `bool`      | [`UniqueSimpleToken<V>`](`UniqueSimpleToken`) |
227/// | `persistent_bool`   | `bool`      | `SimpleToken<V> + Copy` |
228///
229/// The token contains no additional data; its presence indicates that the boolean field
230/// is `true`.
231pub trait SimpleToken : Sized {
232    spec fn instance_id(&self) -> InstanceId;
233
234    /// Return an arbitrary token. It's not possible to do anything interesting
235    /// with this token because it doesn't have a specified instance.
236    proof fn arbitrary() -> (tracked s: Self);
237}
238
239/// Interface for VerusSync tokens created for a field marked with the `bool` strategy.
240///
241/// See the super-trait [`SimpleToken`](SimpleToken) for more information.
242pub trait UniqueSimpleToken : SimpleToken {
243    /// The token for a given instance must be unique; in other words, if we have two
244    /// tokens, they must be for distinct instances.
245    /// Though the first argument is mutable, the value is not really mutated;
246    /// this is only used to ensure unique ownership of the argument.
247    proof fn unique(tracked &mut self, tracked other: &Self)
248        ensures
249            final(self).instance_id() != other.instance_id(),
250            *final(self) == *old(self);
251}
252
253#[verifier::reject_recursive_types(Key)]
254pub tracked struct IMapToken<Key, Value, Token>
255    where Token: KeyValueToken<Key, Value>
256{
257    ghost _v: PhantomData<Value>,
258    ghost inst: InstanceId,
259    tracked m: IMap<Key, Token>,
260}
261
262impl<Key, Value, Token> IMapToken<Key, Value, Token>
263    where Token: KeyValueToken<Key, Value>
264{
265    #[verifier::type_invariant]
266    spec fn wf(self) -> bool {
267        forall |k| #[trigger] self.m.dom().contains(k) ==> self.m[k].key() == k
268            && self.m[k].instance_id() == self.inst
269    }
270
271    pub closed spec fn instance_id(self) -> InstanceId {
272        self.inst
273    }
274
275    pub closed spec fn map(self) -> IMap<Key, Value> {
276        IMap::new(
277            |k: Key| self.m.dom().contains(k),
278            |k: Key| self.m[k].value(),
279        )
280    }
281
282    #[verifier::inline]
283    pub open spec fn dom(self) -> ISet<Key> {
284        self.map().dom()
285    }
286
287    #[verifier::inline]
288    pub open spec fn spec_index(self, k: Key) -> Value {
289        self.map()[k]
290    }
291
292    #[verifier::inline]
293    pub open spec fn index(self, k: Key) -> Value {
294        self.map()[k]
295    }
296
297    pub proof fn empty(instance_id: InstanceId) -> (tracked s: Self)
298        ensures
299            s.instance_id() == instance_id,
300            s.map() == IMap::empty(),
301    {
302        let tracked s = Self { inst: instance_id, m: IMap::tracked_empty(), _v: PhantomData };
303        assert(s.map() =~= IMap::empty());
304        return s;
305    }
306
307    pub proof fn insert(tracked &mut self, tracked token: Token)
308        requires
309            old(self).instance_id() == token.instance_id(),
310        ensures
311            final(self).instance_id() == old(self).instance_id(),
312            final(self).map() == old(self).map().insert(token.key(), token.value()),
313    {
314        use_type_invariant(&*self);
315        self.m.tracked_insert(token.key(), token);
316        assert(self.map() =~= old(self).map().insert(token.key(), token.value()));
317    }
318
319    pub proof fn remove(tracked &mut self, key: Key) -> (tracked token: Token)
320        requires
321            old(self).map().dom().contains(key)
322        ensures
323            final(self).instance_id() == old(self).instance_id(),
324            final(self).map() == old(self).map().remove(key),
325            token.instance_id() == final(self).instance_id(),
326            token.key() == key,
327            token.value() == old(self).map()[key]
328    {
329        use_type_invariant(&*self);
330        let tracked t = self.m.tracked_remove(key);
331        assert(self.map() =~= old(self).map().remove(key));
332        t
333    }
334
335    pub proof fn into_map(tracked self) -> (tracked map: IMap<Key, Token>)
336        ensures
337            map.dom() == self.map().dom(),
338            forall |key|
339                #![trigger(map.dom().contains(key))]
340                #![trigger(map.index(key))]
341              map.dom().contains(key)
342                ==> map[key].instance_id() == self.instance_id()
343                 && map[key].key() == key
344                 && map[key].value() == self.map()[key]
345    {
346        use_type_invariant(&self);
347        let tracked IMapToken { inst, m, _v } = self;
348        assert(m.dom() =~= self.map().dom());
349        return m;
350    }
351
352    pub proof fn from_map(instance_id: InstanceId, tracked map: IMap<Key, Token>) -> (tracked s: Self)
353        requires
354            forall |key| #[trigger] map.dom().contains(key) ==> map[key].instance_id() == instance_id,
355            forall |key| #[trigger] map.dom().contains(key) ==> map[key].key() == key,
356        ensures
357            s.instance_id() == instance_id,
358            s.map().dom() == map.dom(),
359            forall |key| #[trigger] map.dom().contains(key)
360                ==> s.map()[key] == map[key].value()
361    {
362        let tracked s = IMapToken { inst: instance_id, m: map, _v: PhantomData };
363        assert(map.dom() == s.map().dom());
364        s
365    }
366}
367
368#[verifier::reject_recursive_types(Key)]
369pub tracked struct MapToken<Key, Value, Token>
370    where Token: KeyValueToken<Key, Value>
371{
372    ghost _v: PhantomData<Value>,
373    ghost inst: InstanceId,
374    tracked m: Map<Key, Token>,
375}
376
377impl<Key, Value, Token> MapToken<Key, Value, Token>
378    where Token: KeyValueToken<Key, Value>
379{
380    #[verifier::type_invariant]
381    spec fn wf(self) -> bool {
382        forall |k| #[trigger] self.m.dom().contains(k) ==> self.m[k].key() == k
383            && self.m[k].instance_id() == self.inst
384    }
385
386    pub closed spec fn instance_id(self) -> InstanceId {
387        self.inst
388    }
389
390    pub closed spec fn map(self) -> Map<Key, Value> {
391        Map::new(
392            self.m.dom(),
393            |k: Key| self.m[k].value(),
394        )
395    }
396
397    #[verifier::inline]
398    pub open spec fn dom(self) -> Set<Key> {
399        self.map().dom()
400    }
401
402    #[verifier::inline]
403    pub open spec fn spec_index(self, k: Key) -> Value {
404        self.map()[k]
405    }
406
407    #[verifier::inline]
408    pub open spec fn index(self, k: Key) -> Value {
409        self.map()[k]
410    }
411
412    pub proof fn empty(instance_id: InstanceId) -> (tracked s: Self)
413        ensures
414            s.instance_id() == instance_id,
415            s.map() == Map::empty(),
416    {
417        let tracked s = Self { inst: instance_id, m: Map::tracked_empty(), _v: PhantomData };
418        assert(s.map() =~= Map::empty());
419        return s;
420    }
421
422    pub proof fn insert(tracked &mut self, tracked token: Token)
423        requires
424            old(self).instance_id() == token.instance_id(),
425        ensures
426            final(self).instance_id() == old(self).instance_id(),
427            final(self).map() == old(self).map().insert(token.key(), token.value()),
428    {
429        use_type_invariant(&*self);
430        self.m.tracked_insert(token.key(), token);
431        assert(self.map() =~= old(self).map().insert(token.key(), token.value()));
432    }
433
434    pub proof fn remove(tracked &mut self, key: Key) -> (tracked token: Token)
435        requires
436            old(self).map().dom().contains(key)
437        ensures
438            final(self).instance_id() == old(self).instance_id(),
439            final(self).map() == old(self).map().remove(key),
440            token.instance_id() == final(self).instance_id(),
441            token.key() == key,
442            token.value() == old(self).map()[key]
443    {
444        use_type_invariant(&*self);
445        let tracked t = self.m.tracked_remove(key);
446        assert(self.map() =~= old(self).map().remove(key));
447        t
448    }
449
450    pub proof fn into_map(tracked self) -> (tracked map: Map<Key, Token>)
451        ensures
452            map.dom() == self.map().dom(),
453            forall |key|
454                #![trigger(map.dom().contains(key))]
455                #![trigger(map.index(key))]
456              map.dom().contains(key)
457                ==> map[key].instance_id() == self.instance_id()
458                 && map[key].key() == key
459                 && map[key].value() == self.map()[key]
460    {
461        use_type_invariant(&self);
462        let tracked MapToken { inst, m, _v } = self;
463        assert(m.dom() =~= self.map().dom());
464        return m;
465    }
466
467    pub proof fn from_map(instance_id: InstanceId, tracked map: Map<Key, Token>) -> (tracked s: Self)
468        requires
469            forall |key| #[trigger] map.dom().contains(key) ==> map[key].instance_id() == instance_id,
470            forall |key| #[trigger] map.dom().contains(key) ==> map[key].key() == key,
471        ensures
472            s.instance_id() == instance_id,
473            s.map().dom() == map.dom(),
474            forall |key| #[trigger] map.dom().contains(key)
475                ==> s.map()[key] == map[key].value()
476    {
477        let tracked s = MapToken { inst: instance_id, m: map, _v: PhantomData };
478        assert(map.dom() == s.map().dom());
479        s
480    }
481}
482
483#[verifier::reject_recursive_types(Element)]
484pub tracked struct ISetToken<Element, Token>
485    where Token: ElementToken<Element>
486{
487    ghost inst: InstanceId,
488    tracked m: IMap<Element, Token>,
489}
490
491impl<Element, Token> ISetToken<Element, Token>
492    where Token: ElementToken<Element>
493{
494    #[verifier::type_invariant]
495    spec fn wf(self) -> bool {
496        forall |k| #[trigger] self.m.dom().contains(k) ==> self.m[k].element() == k
497            && self.m[k].instance_id() == self.inst
498    }
499
500    pub closed spec fn instance_id(self) -> InstanceId {
501        self.inst
502    }
503
504    pub closed spec fn set(self) -> ISet<Element> {
505        ISet::new(
506            |e: Element| self.m.dom().contains(e),
507        )
508    }
509
510    #[verifier::inline]
511    pub open spec fn contains(self, element: Element) -> bool {
512        self.set().contains(element)
513    }
514
515    pub proof fn empty(instance_id: InstanceId) -> (tracked s: Self)
516        ensures
517            s.instance_id() == instance_id,
518            s.set() == ISet::empty(),
519    {
520        let tracked s = Self { inst: instance_id, m: IMap::tracked_empty() };
521        assert(s.set() =~= ISet::empty());
522        return s;
523    }
524
525    pub proof fn insert(tracked &mut self, tracked token: Token)
526        requires
527            old(self).instance_id() == token.instance_id(),
528        ensures
529            final(self).instance_id() == old(self).instance_id(),
530            final(self).set() == old(self).set().insert(token.element()),
531    {
532        use_type_invariant(&*self);
533        self.m.tracked_insert(token.element(), token);
534        assert(self.set() =~= old(self).set().insert(token.element()));
535    }
536
537    pub proof fn remove(tracked &mut self, element: Element) -> (tracked token: Token)
538        requires
539            old(self).set().contains(element)
540        ensures
541            final(self).instance_id() == old(self).instance_id(),
542            final(self).set() == old(self).set().remove(element),
543            token.instance_id() == final(self).instance_id(),
544            token.element() == element,
545    {
546        use_type_invariant(&*self);
547        let tracked t = self.m.tracked_remove(element);
548        assert(self.set() =~= old(self).set().remove(element));
549        t
550    }
551
552    pub proof fn into_map(tracked self) -> (tracked map: IMap<Element, Token>)
553        ensures
554            map.dom() == self.set(),
555            forall |key|
556                #![trigger(map.dom().contains(key))]
557                #![trigger(map.index(key))]
558                map.dom().contains(key)
559                    ==> map[key].instance_id() == self.instance_id()
560                     && map[key].element() == key
561    {
562        use_type_invariant(&self);
563        let tracked ISetToken { inst, m } = self;
564        assert(m.dom() =~= self.set());
565        return m;
566    }
567
568    pub proof fn from_map(instance_id: InstanceId, tracked map: IMap<Element, Token>) -> (tracked s: Self)
569        requires
570            forall |key| #[trigger] map.dom().contains(key) ==> map[key].instance_id() == instance_id,
571            forall |key| #[trigger] map.dom().contains(key) ==> map[key].element() == key,
572        ensures
573            s.instance_id() == instance_id,
574            s.set() == map.dom(),
575    {
576        let tracked s = ISetToken { inst: instance_id, m: map };
577        assert(s.set() =~= map.dom());
578        s
579    }
580}
581
582#[verifier::reject_recursive_types(Element)]
583pub tracked struct SetToken<Element, Token>
584    where Token: ElementToken<Element>
585{
586    ghost inst: InstanceId,
587    tracked m: Map<Element, Token>,
588}
589
590impl<Element, Token> SetToken<Element, Token>
591    where Token: ElementToken<Element>
592{
593    #[verifier::type_invariant]
594    spec fn wf(self) -> bool {
595        forall |k| #[trigger] self.m.dom().contains(k) ==> self.m[k].element() == k
596            && self.m[k].instance_id() == self.inst
597    }
598
599    pub closed spec fn instance_id(self) -> InstanceId {
600        self.inst
601    }
602
603    pub closed spec fn set(self) -> Set<Element> {
604        self.m.dom()
605    }
606
607    #[verifier::inline]
608    pub open spec fn contains(self, element: Element) -> bool {
609        self.set().contains(element)
610    }
611
612    pub proof fn empty(instance_id: InstanceId) -> (tracked s: Self)
613        ensures
614            s.instance_id() == instance_id,
615            s.set() == Set::empty(),
616    {
617        let tracked s = Self { inst: instance_id, m: Map::tracked_empty() };
618        assert(s.set() =~= Set::empty());
619        return s;
620    }
621
622    pub proof fn insert(tracked &mut self, tracked token: Token)
623        requires
624            old(self).instance_id() == token.instance_id(),
625        ensures
626            final(self).instance_id() == old(self).instance_id(),
627            final(self).set() == old(self).set().insert(token.element()),
628    {
629        use_type_invariant(&*self);
630        self.m.tracked_insert(token.element(), token);
631        assert(self.set() =~= old(self).set().insert(token.element()));
632    }
633
634    pub proof fn remove(tracked &mut self, element: Element) -> (tracked token: Token)
635        requires
636            old(self).set().contains(element)
637        ensures
638            final(self).instance_id() == old(self).instance_id(),
639            final(self).set() == old(self).set().remove(element),
640            token.instance_id() == final(self).instance_id(),
641            token.element() == element,
642    {
643        use_type_invariant(&*self);
644        let tracked t = self.m.tracked_remove(element);
645        assert(self.set() =~= old(self).set().remove(element));
646        t
647    }
648
649    pub proof fn into_map(tracked self) -> (tracked map: Map<Element, Token>)
650        ensures
651            map.dom() == self.set(),
652            forall |key|
653                #![trigger(map.dom().contains(key))]
654                #![trigger(map.index(key))]
655                map.dom().contains(key)
656                    ==> map[key].instance_id() == self.instance_id()
657                     && map[key].element() == key
658    {
659        use_type_invariant(&self);
660        let tracked SetToken { inst, m } = self;
661        assert(m.dom() =~= self.set());
662        return m;
663    }
664
665    pub proof fn from_map(instance_id: InstanceId, tracked map: Map<Element, Token>) -> (tracked s: Self)
666        requires
667            forall |key| #[trigger] map.dom().contains(key) ==> map[key].instance_id() == instance_id,
668            forall |key| #[trigger] map.dom().contains(key) ==> map[key].element() == key,
669        ensures
670            s.instance_id() == instance_id,
671            s.set() == map.dom(),
672    {
673        let tracked s = SetToken { inst: instance_id, m: map };
674        assert(s.set() =~= map.dom());
675        s
676    }
677}
678
679pub tracked struct MultisetToken<Element, Token>
680    where Token: ElementToken<Element>
681{
682    ghost _v: PhantomData<Element>,
683    ghost inst: InstanceId,
684    tracked m: IMap<int, Token>,
685}
686
687spec fn map_values<K, V>(m: IMap<K, V>) -> Multiset<V> {
688    m.dom().fold(Multiset::empty(), |multiset: Multiset<V>, k: K| multiset.insert(m[k]))
689}
690
691proof fn map_values_insert_not_in<K, V>(m: IMap<K, V>, k: K, v: V)
692    requires
693        !m.dom().contains(k)
694    ensures
695        map_values(m.insert(k, v)) == map_values(m).insert(v)
696{
697    assume(false);
698}
699
700proof fn map_values_remove<K, V>(m: IMap<K, V>, k: K)
701    requires
702        m.dom().contains(k)
703    ensures
704        map_values(m.remove(k)) == map_values(m).remove(m[k])
705{
706    assume(false);
707}
708
709//proof fn map_values_empty_empty<K, V>()
710//    ensures map_values(IMap::<K, V>::empty()) == Multiset::empty(),
711
712spec fn fresh(m: ISet<int>) -> int {
713    m.find_unique_maximal(|a: int, b: int| a <= b) + 1
714}
715
716proof fn fresh_is_fresh(s: ISet<int>)
717    requires s.finite(),
718    ensures !s.contains(fresh(s))
719{
720    assume(false);
721}
722
723proof fn get_key_for_value<K, V>(m: IMap<K, V>, value: V) -> (k: K)
724    requires map_values(m).contains(value),
725    ensures m.dom().contains(k), m[k] == value,
726{
727    assume(false);
728    arbitrary()
729}
730
731impl<Element, Token> MultisetToken<Element, Token>
732    where Token: ElementToken<Element>
733{
734    #[verifier::type_invariant]
735    spec fn wf(self) -> bool {
736        self.m.dom().finite() &&
737        forall |k| #[trigger] self.m.dom().contains(k)
738            ==> self.m[k].instance_id() == self.inst
739    }
740
741    pub closed spec fn instance_id(self) -> InstanceId {
742        self.inst
743    }
744
745    spec fn map_elems(m: IMap<int, Token>) -> IMap<int, Element> {
746        m.map_values(|t: Token| t.element())
747    }
748
749    pub closed spec fn multiset(self) -> Multiset<Element> {
750        map_values(Self::map_elems(self.m))
751    }
752
753    pub proof fn empty(instance_id: InstanceId) -> (tracked s: Self)
754        ensures
755            s.instance_id() == instance_id,
756            s.multiset() == Multiset::empty(),
757    {
758        let tracked s = Self { inst: instance_id, m: IMap::tracked_empty(), _v: PhantomData, };
759        broadcast use super::iset::fold::lemma_fold_empty;
760        assert(Self::map_elems(IMap::empty()) =~= IMap::empty());
761        return s;
762    }
763
764    pub proof fn insert(tracked &mut self, tracked token: Token)
765        requires
766            old(self).instance_id() == token.instance_id(),
767        ensures
768            final(self).instance_id() == old(self).instance_id(),
769            final(self).multiset() == old(self).multiset().insert(token.element()),
770    {
771        use_type_invariant(&*self);
772        let f = fresh(self.m.dom());
773        fresh_is_fresh(self.m.dom());
774        map_values_insert_not_in(
775            Self::map_elems(self.m),
776            f,
777            token.element());
778        self.m.tracked_insert(f, token);
779        assert(Self::map_elems(self.m) =~= Self::map_elems(old(self).m).insert(
780            f, token.element()));
781        assert(self.multiset() =~= old(self).multiset().insert(token.element()));
782    }
783
784    pub proof fn remove(tracked &mut self, element: Element) -> (tracked token: Token)
785        requires
786            old(self).multiset().contains(element)
787        ensures
788            final(self).instance_id() == old(self).instance_id(),
789            final(self).multiset() == old(self).multiset().remove(element),
790            token.instance_id() == final(self).instance_id(),
791            token.element() == element,
792    {
793        use_type_invariant(&*self);
794        assert(Self::map_elems(self.m).dom() =~= self.m.dom());
795        let k = get_key_for_value(Self::map_elems(self.m), element);
796        map_values_remove(Self::map_elems(self.m), k);
797        let tracked t = self.m.tracked_remove(k);
798        assert(Self::map_elems(self.m) =~= Self::map_elems(old(self).m).remove(k));
799        assert(self.multiset() =~= old(self).multiset().remove(element));
800        t
801    }
802}
803
804pub open spec fn option_value_eq_option_token<Value, Token: ValueToken<Value>>(
805    opt_value: Option<Value>,
806    opt_token: Option<Token>,
807    instance_id: InstanceId,
808) -> bool {
809    match opt_value {
810        Some(val) => opt_token.is_some()
811            && opt_token.unwrap().value() == val
812            && opt_token.unwrap().instance_id() == instance_id,
813        None => opt_token.is_none(),
814    }
815}
816
817pub open spec fn option_value_le_option_token<Value, Token: ValueToken<Value>>(
818    opt_value: Option<Value>,
819    opt_token: Option<Token>,
820    instance_id: InstanceId,
821) -> bool {
822    match opt_value {
823        Some(val) => opt_token.is_some()
824            && opt_token.unwrap().value() == val
825            && opt_token.unwrap().instance_id() == instance_id,
826        None => true,
827    }
828}
829
830pub open spec fn bool_value_eq_option_token<Token: SimpleToken>(
831    b: bool,
832    opt_token: Option<Token>,
833    instance_id: InstanceId,
834) -> bool {
835    if b {
836        opt_token.is_some() && opt_token.unwrap().instance_id() == instance_id
837    } else {
838        opt_token.is_none()
839    }
840}
841
842pub open spec fn bool_value_le_option_token<Token: SimpleToken>(
843    b: bool,
844    opt_token: Option<Token>,
845    instance_id: InstanceId,
846) -> bool {
847    b ==>
848        opt_token.is_some() && opt_token.unwrap().instance_id() == instance_id
849}
850
851}