#[ravencheck::check_module]
#[declare_types(u32)]
mod my_mod {
use std::collections::HashSet;
#[declare]
type MySet = HashSet<u32>;
#[define]
type MySetAlias = MySet;
#[declare]
pub 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]
pub fn empty_set() -> MySet {
HashSet::new()
}
#[assume]
fn empty_set_no_member() -> bool {
forall(|e: u32| {
!member(e, empty_set())
})
}
#[declare]
pub fn union(a: MySet, b: MySetAlias) -> MySetAlias {
a.union(&b).cloned().collect()
}
#[annotate(union)]
fn union_def() -> bool {
|a: MySet, b: MySet|
|c: MySet|
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]
pub fn insert(e: u32, mut s: MySet) -> MySet {
s.insert(e);
s
}
#[annotate(insert)]
fn insert_def() -> bool {
|e: u32, s1: MySet|
|s2: MySet|
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]
pub 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())
)
}
}
}
fn main() {
let s = my_mod::empty_set();
let result1 = my_mod::union(s.clone(), s.clone()) == s;
println!("Result #1 is {}", result1);
let s2 = my_mod::insert(2, my_mod::singleton(1));
let result2 = my_mod::member(1, s2.clone()) && my_mod::member(2, s2);
println!("Result #2 is {}", result2);
}