use super::super::map::*;
use super::super::map_lib::*;
use super::super::modes::*;
use super::super::prelude::*;
use super::super::set::*;
use super::super::set_lib::*;
use super::Loc;
use super::map::GhostMapAuth;
use super::map::GhostPersistentPointsTo;
use super::map::GhostPersistentSubmap;
use super::map::GhostPointsTo;
use super::map::GhostSubmap;
verus! {
broadcast use super::super::group_vstd_default;
#[verifier::reject_recursive_types(T)]
pub struct GhostSetAuth<T> {
map: GhostMapAuth<T, ()>,
}
#[verifier::reject_recursive_types(T)]
pub struct GhostSubset<T> {
map: GhostSubmap<T, ()>,
}
#[verifier::reject_recursive_types(T)]
pub struct GhostPersistentSubset<T> {
map: GhostPersistentSubmap<T, ()>,
}
#[verifier::reject_recursive_types(T)]
pub struct GhostSingleton<T> {
map: GhostPointsTo<T, ()>,
}
#[verifier::reject_recursive_types(T)]
pub struct GhostPersistentSingleton<T> {
map: GhostPersistentPointsTo<T, ()>,
}
impl<T> GhostSetAuth<T> {
pub closed spec fn id(self) -> Loc {
self.map.id()
}
pub closed spec fn view(self) -> ISet<T> {
self.map@.dom()
}
pub proof fn new(s: ISet<T>) -> (tracked result: (GhostSetAuth<T>, GhostSubset<T>))
ensures
result.0.id() == result.1.id(),
result.0@ == s,
result.1@ == s,
{
let m = s.mk_map(|k: T| ());
let tracked (map, submap) = GhostMapAuth::new(m);
(GhostSetAuth { map }, GhostSubset { map: submap })
}
pub proof fn dummy() -> (tracked result: GhostSetAuth<T>) {
let tracked map = GhostMapAuth::dummy();
GhostSetAuth { map }
}
pub proof fn take(tracked &mut self) -> (tracked result: GhostSetAuth<T>)
ensures
result == *old(self),
{
let tracked map = self.map.take();
GhostSetAuth { map }
}
pub proof fn empty(tracked &self) -> (tracked result: GhostSubset<T>)
ensures
result.id() == self.id(),
result@ == ISet::<T>::empty(),
{
let tracked map = self.map.empty();
GhostSubset { map }
}
pub proof fn insert_set(tracked &mut self, s: ISet<T>) -> (tracked result: GhostSubset<T>)
requires
old(self)@.disjoint(s),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.union(s),
result.id() == final(self).id(),
result@ == s,
{
let m = s.mk_map(|k: T| ());
let tracked submap = self.map.insert_map(m);
GhostSubset { map: submap }
}
pub proof fn insert(tracked &mut self, v: T) -> (tracked result: GhostSingleton<T>)
requires
!old(self)@.contains(v),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.insert(v),
result.id() == final(self).id(),
result@ == v,
{
let tracked map = self.map.insert(v, ());
GhostSingleton { map }
}
pub proof fn delete(tracked &mut self, tracked f: GhostSubset<T>)
requires
f.id() == old(self).id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.difference(f@),
{
self.map.delete(f.map);
}
pub proof fn delete_singleton(tracked &mut self, tracked p: GhostSingleton<T>)
requires
p.id() == old(self).id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.remove(p@),
{
self.map.delete_points_to(p.map);
}
}
impl<T> GhostSubset<T> {
pub open spec fn is_singleton(self) -> bool {
&&& self@.len() == 1
&&& self@.finite()
&&& !self@.is_empty()
}
pub closed spec fn id(self) -> Loc {
self.map.id()
}
pub closed spec fn view(self) -> ISet<T> {
self.map@.dom()
}
pub proof fn dummy() -> (tracked result: GhostSubset<T>) {
let tracked map = GhostSubmap::dummy();
GhostSubset { map }
}
pub proof fn empty(tracked &self) -> (tracked result: GhostSubset<T>)
ensures
result.id() == self.id(),
result@ == ISet::<T>::empty(),
{
let tracked map = self.map.empty();
GhostSubset { map }
}
pub proof fn take(tracked &mut self) -> (tracked result: GhostSubset<T>)
ensures
old(self).id() == final(self).id(),
final(self)@.is_empty(),
result == *old(self),
result.id() == final(self).id(),
{
let tracked map = self.map.take();
GhostSubset { map }
}
pub proof fn agree(tracked self: &GhostSubset<T>, tracked auth: &GhostSetAuth<T>)
requires
self.id() == auth.id(),
ensures
self@ <= auth@,
{
self.map.agree(&auth.map);
}
pub proof fn combine(tracked &mut self, tracked other: GhostSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.union(other@),
old(self)@.disjoint(other@),
{
self.map.combine(other.map);
}
pub proof fn combine_singleton(tracked &mut self, tracked other: GhostSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.insert(other@),
!old(self)@.contains(other@),
{
self.map.combine_points_to(other.map);
}
pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
final(self)@.disjoint(other@),
{
self.map.disjoint(&other.map);
}
pub proof fn disjoint_persistent(tracked &mut self, tracked other: &GhostPersistentSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
final(self)@.disjoint(other@),
{
self.map.disjoint_persistent(&other.map);
}
pub proof fn disjoint_singleton(tracked &mut self, tracked other: &GhostSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
!final(self)@.contains(other@),
{
self.map.disjoint_points_to(&other.map);
}
pub proof fn disjoint_persistent_singleton(
tracked &mut self,
tracked other: &GhostPersistentSingleton<T>,
)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
!final(self)@.contains(other@),
{
self.map.disjoint_persistent_points_to(&other.map);
}
pub proof fn split(tracked &mut self, s: ISet<T>) -> (tracked result: GhostSubset<T>)
requires
s <= old(self)@,
ensures
final(self).id() == old(self).id(),
result.id() == final(self).id(),
old(self)@ == final(self)@.union(result@),
result@ =~= s,
final(self)@ =~= old(self)@ - s,
{
let tracked map = self.map.split(s);
GhostSubset { map }
}
pub proof fn split_singleton(tracked &mut self, v: T) -> (tracked result: GhostSingleton<T>)
requires
old(self)@.contains(v),
ensures
final(self).id() == old(self).id(),
result.id() == final(self).id(),
old(self)@ == final(self)@.insert(result@),
result@ == v,
final(self)@ =~= old(self)@.remove(v),
{
let tracked map = self.map.split_points_to(v);
GhostSingleton { map }
}
pub proof fn singleton(tracked self) -> (tracked r: GhostSingleton<T>)
requires
self.is_singleton(),
ensures
self@ == iset![r@],
self.id() == r.id(),
{
let tracked map = self.map.points_to();
GhostSingleton { map }
}
pub proof fn persist(tracked self) -> (tracked r: GhostPersistentSubset<T>)
ensures
self@ == r@,
self.id() == r.id(),
{
let tracked map = self.map.persist();
GhostPersistentSubset { map }
}
}
impl<T> GhostPersistentSubset<T> {
pub open spec fn is_singleton(self) -> bool {
&&& self@.len() == 1
&&& self@.finite()
&&& !self@.is_empty()
}
pub closed spec fn id(self) -> Loc {
self.map.id()
}
pub closed spec fn view(self) -> ISet<T> {
self.map@.dom()
}
pub proof fn dummy() -> (tracked result: GhostPersistentSubset<T>) {
let tracked map = GhostPersistentSubmap::dummy();
GhostPersistentSubset { map }
}
pub proof fn empty(tracked &self) -> (tracked result: GhostPersistentSubset<T>)
ensures
result.id() == self.id(),
result@ == ISet::<T>::empty(),
{
let tracked map = self.map.empty();
GhostPersistentSubset { map }
}
pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentSubset<T>)
ensures
result@ == self@,
result.id() == self.id(),
{
let tracked map = self.map.duplicate();
GhostPersistentSubset { map }
}
pub proof fn agree(tracked self: &GhostPersistentSubset<T>, tracked auth: &GhostSetAuth<T>)
requires
self.id() == auth.id(),
ensures
self@ <= auth@,
{
self.map.agree(&auth.map);
}
pub proof fn combine(tracked &mut self, tracked other: GhostPersistentSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.union(other@),
{
self.map.combine(other.map);
}
pub proof fn combine_points_to(tracked &mut self, tracked other: GhostPersistentSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@.insert(other@),
{
self.map.combine_points_to(other.map);
}
pub proof fn disjoint(tracked &mut self, tracked other: &GhostSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
final(self)@.disjoint(other@),
{
self.map.disjoint(&other.map);
}
pub proof fn disjoint_singleton(tracked &mut self, tracked other: &GhostSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
!final(self)@.contains(other@),
{
self.map.disjoint_points_to(&other.map);
}
pub proof fn split(tracked &mut self, s: ISet<T>) -> (tracked result: GhostPersistentSubset<T>)
requires
s <= old(self)@,
ensures
final(self).id() == old(self).id(),
result.id() == final(self).id(),
old(self)@ == final(self)@.union(result@),
result@ =~= s,
final(self)@ =~= old(self)@ - s,
{
let tracked map = self.map.split(s);
GhostPersistentSubset { map }
}
pub proof fn split_singleton(tracked &mut self, v: T) -> (tracked result:
GhostPersistentSingleton<T>)
requires
old(self)@.contains(v),
ensures
final(self).id() == old(self).id(),
result.id() == final(self).id(),
old(self)@ == final(self)@.insert(result@),
result@ == v,
final(self)@ =~= old(self)@.remove(v),
{
let tracked map = self.map.split_points_to(v);
GhostPersistentSingleton { map }
}
pub proof fn singleton(tracked self) -> (tracked r: GhostPersistentSingleton<T>)
requires
self.is_singleton(),
ensures
self@ == iset![r@],
self.id() == r.id(),
{
let tracked map = self.map.points_to();
GhostPersistentSingleton { map }
}
}
impl<T> GhostSingleton<T> {
pub closed spec fn id(self) -> Loc {
self.map.id()
}
pub closed spec fn view(self) -> T {
self.map@.0
}
pub proof fn agree(tracked self: &GhostSingleton<T>, tracked auth: &GhostSetAuth<T>)
requires
self.id() == auth.id(),
ensures
auth@.contains(self@),
{
self.map.agree(&auth.map);
}
pub proof fn combine(tracked self, tracked other: GhostSingleton<T>) -> (tracked r: GhostSubset<
T,
>)
requires
self.id() == other.id(),
ensures
r.id() == self.id(),
r@ == iset![self@, other@],
self@ != other@,
{
let tracked map = self.map.combine(other.map);
GhostSubset { map }
}
pub proof fn disjoint(tracked &mut self, tracked other: &GhostSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
final(self)@ != other@,
{
self.map.disjoint(&other.map)
}
pub proof fn disjoint_persistent(tracked &mut self, tracked other: &GhostPersistentSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
final(self)@ != other@,
{
self.map.disjoint_persistent(&other.map)
}
pub proof fn disjoint_subset(tracked &mut self, tracked other: &GhostSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
!other@.contains(final(self)@),
{
self.map.disjoint_submap(&other.map);
}
pub proof fn disjoint_persistent_subset(
tracked &mut self,
tracked other: &GhostPersistentSubset<T>,
)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
!other@.contains(final(self)@),
{
self.map.disjoint_persistent_submap(&other.map);
}
pub proof fn subset(tracked self) -> (tracked r: GhostSubset<T>)
ensures
r.id() == self.id(),
r@ == iset![self@],
{
let tracked map = self.map.submap();
GhostSubset { map }
}
pub proof fn persist(tracked self) -> (tracked r: GhostPersistentSingleton<T>)
ensures
self@ == r@,
self.id() == r.id(),
{
let tracked map = self.map.persist();
GhostPersistentSingleton { map }
}
}
impl<T> GhostPersistentSingleton<T> {
pub closed spec fn id(self) -> Loc {
self.map.id()
}
pub closed spec fn view(self) -> T {
self.map@.0
}
pub proof fn duplicate(tracked &self) -> (tracked result: GhostPersistentSingleton<T>)
ensures
result@ == self@,
result.id() == self.id(),
{
let tracked map = self.map.duplicate();
GhostPersistentSingleton { map }
}
pub proof fn agree(tracked self: &GhostPersistentSingleton<T>, tracked auth: &GhostSetAuth<T>)
requires
self.id() == auth.id(),
ensures
auth@.contains(self@),
{
self.map.agree(&auth.map);
}
pub proof fn combine(tracked self, tracked other: GhostPersistentSingleton<T>) -> (tracked r:
GhostPersistentSubset<T>)
requires
self.id() == other.id(),
ensures
r.id() == self.id(),
r@ == iset![self@, other@],
self@ != other@ ==> r@.len() == 2,
self@ == other@ ==> r@.len() == 1,
{
let tracked map = self.map.combine(other.map);
GhostPersistentSubset { map }
}
pub proof fn disjoint(tracked &mut self, tracked other: &GhostSingleton<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
final(self)@ != other@,
{
self.map.disjoint(&other.map)
}
pub proof fn disjoint_subset(tracked &mut self, tracked other: &GhostSubset<T>)
requires
old(self).id() == other.id(),
ensures
final(self).id() == old(self).id(),
final(self)@ == old(self)@,
!other@.contains(final(self)@),
{
self.map.disjoint_submap(&other.map);
}
pub proof fn subset(tracked self) -> (tracked r: GhostPersistentSubset<T>)
ensures
r.id() == self.id(),
r@ == iset![self@],
{
let tracked map = self.map.submap();
GhostPersistentSubset { map }
}
}
}