#[crate::check_module(crate)]
#[declare_types(u32)]
#[allow(dead_code)]
mod my_mod {
use std::collections::HashSet;
#[declare]
type MySet = HashSet<u32>;
#[define]
type MySetAlias = MySet;
#[declare]
fn member(e: u32, s: MySet) -> bool {
s.contains(&e)
}
#[assume]
fn equal_or_distinguisher() -> bool {
forall(|a:MySet,b:MySet| {
a == b || exists(|e:u32| member(e,a) != member(e,b))
})
}
#[declare]
fn empty_set() -> MySet {
HashSet::new()
}
#[assume]
fn empty_set_no_member() -> bool {
forall(|e: u32| {
!member(e, empty_set())
})
}
#[declare]
fn union(a: MySet, b: MySetAlias) -> MySetAlias {
a.union(&b).cloned().collect()
}
#[assume(union(a,b) => c)]
fn union_def() -> bool {
forall(|e: u32| {
member(e,c) == (member(e,a) || member(e,b))
})
}
#[verify]
fn union_idempotent() -> bool {
forall(|a: MySetAlias, b: MySet| {
union(union(a,b), b) == union(a,b)
})
}
#[declare]
fn insert(e: u32, mut s: MySet) -> MySet {
s.insert(e);
s
}
#[assume(insert(e,s1) => s2)]
fn insert_def() -> bool {
forall(|x:u32| member(x,s2) == (member(x,s1) || x == e))
}
#[verify]
fn insert_monotonic() -> bool {
forall(|e1: u32, e2: u32, s: MySet| {
implies(
member(e1,s),
member(e1, insert(e2,s)),
)
})
}
#[define]
fn singleton(e: u32) -> MySet {
insert(e, empty_set())
}
#[verify]
fn singleton_membership() -> bool {
forall(|e1: u32, e2: u32| {
member(e1, singleton(e2)) == (e1 == e2)
})
}
#[cfg(test)]
mod normal_tests {
use super::*;
#[test]
fn union_empty_set() {
assert!(
union(empty_set(), empty_set()) == empty_set()
)
}
#[test]
fn empty_is_empty() {
assert!(
!member(1, empty_set())
)
}
}
}