pub struct FSet<T>(/* private fields */);Expand description
A finite set type usable in pearlite and ghost! blocks.
If you need an infinite set, see Set.
§Ghost
Since std::collections::HashSet and
std::collections::BTreeSet have finite
capacity, this could cause some issues in ghost code:
ghost! {
let mut set = HashSet::new();
for _ in 0..=usize::MAX as u128 + 1 {
set.insert(0); // cannot fail, since we are in a ghost block
}
proof_assert!(set.len() <= usize::MAX@); // by definition
proof_assert!(set.len() > usize::MAX@); // uh-oh
}This type is designed for this use-case, with no restriction on the capacity.
Implementations§
Source§impl<T> FSet<T>
impl<T> FSet<T>
Sourcepub fn contains(self, e: T) -> bool
pub fn contains(self, e: T) -> bool
Returns true if e is in the set.
logic(open, inline)
Self::mem(e, self)Sourcepub fn insert(self, e: T) -> Self
pub fn insert(self, e: T) -> Self
Returns a new set, where e has been added if it was not present.
logic(open, inline)
Self::add(e, self)Sourcepub fn remove(self, e: T) -> Self
pub fn remove(self, e: T) -> Self
Returns a new set, where e is no longer present.
logic(open, inline)
Self::rem(e, self)Sourcepub fn union(self, other: Self) -> Self
pub fn union(self, other: Self) -> Self
Returns a new set, which is the union of self and other.
An element is in the result if it is in self or if it is in other.
logic ⚠
Sourcepub fn intersection(self, other: Self) -> Self
pub fn intersection(self, other: Self) -> Self
Returns a new set, which is the union of self and other.
An element is in the result if it is in self or if it is in other.
logic ⚠
Sourcepub fn difference(self, other: Self) -> Self
pub fn difference(self, other: Self) -> Self
Returns a new set, which is the difference of self with other.
An element is in the result if and only if it is in self but not in other.
logic ⚠
Sourcepub fn is_subset(self, other: Self) -> bool
pub fn is_subset(self, other: Self) -> bool
Returns true if every element of self is in other.
logic ⚠
Sourcepub fn is_superset(self, other: Self) -> bool
pub fn is_superset(self, other: Self) -> bool
Returns true if every element of other is in self.
logic(open, inline)
Self::is_subset(other, self)Sourcepub fn disjoint(self, other: Self) -> bool
pub fn disjoint(self, other: Self) -> bool
Returns true if self and other are disjoint.
logic ⚠
Sourcepub fn len(self) -> Int
pub fn len(self) -> Int
Returns the number of elements in the set, also called its length.
logic ⚠
Sourcepub fn peek(self) -> T
pub fn peek(self) -> T
Get an arbitrary element of the set.
§Returns
- If the set is nonempty, the result is guaranteed to be in the set
- If the set is empty, the result is unspecified
logic ⚠
Sourcepub fn ext_eq(self, other: Self) -> bool
pub fn ext_eq(self, other: Self) -> bool
Extensional equality
Returns true if self and other contain exactly the same elements.
This is in fact equivalent with normal equality.
logic(open)
forall <e: T> self.contains(e) == other.contains(e)ensures
result == (self == other)Sourcepub fn singleton(x: T) -> Self
pub fn singleton(x: T) -> Self
Returns the set containing only x.
logic(open)
FSet::empty().insert(x)ensures
forall<y: T> result.contains(y) == (x == y)Sourcepub fn unions<U>(self, f: Mapping<T, FSet<U>>) -> FSet<U>
pub fn unions<U>(self, f: Mapping<T, FSet<U>>) -> FSet<U>
Returns the union of sets f(t) over all t: T.
logic(open)
if self.len() == 0 { FSet::empty() } else { let x = self.peek(); f.get(x).union(self.remove(x).unions(f)) }
ensures
forall<y: U> result.contains(y) == exists<x: T> self.contains(x) && f.get(x).contains(y)
Sourcepub fn map<U>(self, f: Mapping<T, U>) -> FSet<U>
pub fn map<U>(self, f: Mapping<T, U>) -> FSet<U>
Returns the image of a set by a function.
logic(open)
FSet::fmap(f, self)Sourcepub fn filter(self, f: Mapping<T, bool>) -> Self
pub fn filter(self, f: Mapping<T, bool>) -> Self
Returns the subset of elements of self which satisfy the predicate f.
logic ⚠
Sourcepub fn cons(s: FSet<T>, ss: FSet<Seq<T>>) -> FSet<Seq<T>>
pub fn cons(s: FSet<T>, ss: FSet<Seq<T>>) -> FSet<Seq<T>>
Returns the set of sequences whose head is in s and whose tail is in ss.
logic(open)
proof_assert!(forall<x:T, xs: Seq<T>> xs.push_front(x).tail() == xs); proof_assert!(forall<xs: Seq<T>> 0 < xs.len() ==> xs.tail().push_front(xs[0]) == xs); s.unions(|x| ss.map(|xs: Seq<_>| xs.push_front(x)))
ensures
forall<xs: Seq<T>> result.contains(xs) == (0 < xs.len() && s.contains(xs[0]) && ss.contains(xs.tail()))
Sourcepub fn concat(s: FSet<Seq<T>>, t: FSet<Seq<T>>) -> FSet<Seq<T>>
pub fn concat(s: FSet<Seq<T>>, t: FSet<Seq<T>>) -> FSet<Seq<T>>
Returns the set of concatenations of a sequence in s and a sequence in t.
logic(open)
s.unions(|ys: Seq<_>| t.map(|zs| ys.concat(zs)))ensures
forall<xs: Seq<T>> result.contains(xs) == (exists<ys: Seq<T>, zs: Seq<T>> s.contains(ys) && t.contains(zs) && xs == ys.concat(zs))
Sourcepub fn replicate(self, n: Int) -> FSet<Seq<T>>
pub fn replicate(self, n: Int) -> FSet<Seq<T>>
Returns the set of sequences of length n whose elements are in self.
logic(open)
/* Macro-generated */requires
n >= 0ensures
forall<xs: Seq<T>> result.contains(xs) == (xs.len() == n && forall<x: T> xs.contains(x) ==> self.contains(x))
Sourcepub fn replicate_up_to(self, n: Int) -> FSet<Seq<T>>
pub fn replicate_up_to(self, n: Int) -> FSet<Seq<T>>
Returns the set of sequences of length at most n whose elements are in self.
logic(open)
if n == 0 { proof_assert! { forall<xs: Seq<T>> xs.len() == 0 ==> xs == Seq::empty() }; FSet::singleton(Seq::empty()) } else { self.replicate_up_to(n - 1).union(self.replicate(n)) }
requires
n >= 0ensures
forall<xs: Seq<T>> result.contains(xs) == (xs.len() <= n && forall<x: T> xs.contains(x) ==> self.contains(x))
Sourcepub fn unions_union<U>(
self,
other: Self,
f: Mapping<T, FSet<U>>,
g: Mapping<T, FSet<U>>,
)
pub fn unions_union<U>( self, other: Self, f: Mapping<T, FSet<U>>, g: Mapping<T, FSet<U>>, )
Distributivity of unions over union.
logic ⚠
ensures
self.union(other).unions(f) == self.unions(f).union(other.unions(f))ensures
self.unions(|x| f.get(x).union(g.get(x))) == self.unions(f).union(self.unions(g))
Sourcepub fn map_union<U>(self, other: Self, f: Mapping<T, U>)
pub fn map_union<U>(self, other: Self, f: Mapping<T, U>)
Distributivity of map over union.
logic ⚠
ensures
self.union(other).map(f) == self.map(f).union(other.map(f))Sourcepub fn concat_union(s1: FSet<Seq<T>>, s2: FSet<Seq<T>>, t: FSet<Seq<T>>)
pub fn concat_union(s1: FSet<Seq<T>>, s2: FSet<Seq<T>>, t: FSet<Seq<T>>)
Distributivity of concat over union.
logic ⚠
ensures
FSet::concat(s1.union(s2), t) == FSet::concat(s1, t).union(FSet::concat(s2, t))
ensures
FSet::concat(t, s1.union(s2)) == FSet::concat(t, s1).union(FSet::concat(t, s2))
Sourcepub fn cons_concat(self, t: FSet<Seq<T>>, u: FSet<Seq<T>>)
pub fn cons_concat(self, t: FSet<Seq<T>>, u: FSet<Seq<T>>)
Distributivity of cons over union.
logic ⚠
ensures
FSet::concat(FSet::cons(self, t), u) == FSet::cons(self, FSet::concat(t, u))
Sourcepub fn concat_replicate(self, n: Int, m: Int)
pub fn concat_replicate(self, n: Int, m: Int)
Distributivity of replicate over union.
logic ⚠
requires
0 <= n && 0 <= mensures
self.replicate(n + m) == FSet::concat(self.replicate(n), self.replicate(m))
Sourcepub fn concat_empty(s: FSet<Seq<T>>)
pub fn concat_empty(s: FSet<Seq<T>>)
The neutral element of FSet::concat is FSet::singleton(Seq::empty()).
logic ⚠
ensures
FSet::concat(FSet::singleton(Seq::empty()), s) == sensures
FSet::concat(s, FSet::singleton(Seq::empty())) == sSourcepub fn concat_replicate_up_to(self, n: Int, m: Int)
pub fn concat_replicate_up_to(self, n: Int, m: Int)
An equation relating s.replicate_up_to(m) and s.replicate_up_to(n).
logic ⚠
requires
0 <= n && n < mensures
self.replicate_up_to(m) == self.replicate_up_to(n).union( FSet::concat(self.replicate(n + 1), self.replicate_up_to(m - n - 1)))
Source§impl<T> FSet<T>
Ghost definitions
impl<T> FSet<T>
Ghost definitions
Sourcepub fn new() -> Ghost<Self>
pub fn new() -> Ghost<Self>
Create a new, empty set on the ghost heap.
terminates
ghost
ensures
result.is_empty()Sourcepub fn len_ghost(&self) -> Int
pub fn len_ghost(&self) -> Int
Returns the number of elements in the set.
If you need to get the length in pearlite, consider using len.
§Example
use creusot_std::{logic::FSet, prelude::*};
let mut set = FSet::new();
ghost! {
let len1 = set.len_ghost();
set.insert_ghost(1);
set.insert_ghost(2);
set.insert_ghost(1);
let len2 = set.len_ghost();
proof_assert!(len1 == 0);
proof_assert!(len2 == 2);
};terminates
ghost
ensures
result == self.len()Sourcepub fn contains_ghost(&self, value: &T) -> bool
pub fn contains_ghost(&self, value: &T) -> bool
Returns true if the set contains the specified value.
§Example
use creusot_std::{logic::FSet, prelude::*};
let mut set = FSet::new();
ghost! {
set.insert_ghost(1);
let (b1, b2) = (set.contains_ghost(&1), set.contains_ghost(&2));
proof_assert!(b1);
proof_assert!(!b2);
};terminates
ghost
ensures
result == self.contains(*value)Sourcepub fn insert_ghost(&mut self, value: T) -> bool
pub fn insert_ghost(&mut self, value: T) -> bool
Adds a value to the set.
Returns whether the value was newly inserted. That is:
- If the set did not previously contain this value,
trueis returned. - If the set already contained this value,
falseis returned, and the set is not modified: original value is not replaced, and the value passed as argument is dropped.
§Example
use creusot_std::{logic::FSet, prelude::*};
let mut set = FSet::new();
ghost! {
let res1 = set.insert_ghost(42);
proof_assert!(res1);
proof_assert!(set.contains(42i32));
let res2 = set.insert_ghost(41);
let res3 = set.insert_ghost(42);
proof_assert!(res2);
proof_assert!(!res3);
proof_assert!(set.len() == 2);
};terminates
ghost
ensures
^self == (*self).insert(value)ensures
result == !(*self).contains(value)Sourcepub fn remove_ghost(&mut self, value: &T) -> bool
pub fn remove_ghost(&mut self, value: &T) -> bool
Removes a value from the set. Returns whether the value was present in the set.
§Example
use creusot_std::{logic::FSet, prelude::*};
let mut set = FSet::new();
let res = ghost! {
set.insert_ghost(1);
let res1 = set.remove_ghost(&1);
let res2 = set.remove_ghost(&1);
proof_assert!(res1 && !res2);
};terminates
ghost
ensures
^self == (*self).remove(*value)ensures
result == (*self).contains(*value)Sourcepub fn clear_ghost(&mut self)
pub fn clear_ghost(&mut self)
Clears the set, removing all values.
§Example
use creusot_std::{prelude::*, logic::FSet};
let mut s = FSet::new();
ghost! {
s.insert_ghost(1);
s.insert_ghost(2);
s.insert_ghost(3);
s.clear_ghost();
proof_assert!(s == FSet::empty());
};terminates
ghost
ensures
^self == Self::empty()