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.
(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.
(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.
(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.
⚠
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.
⚠
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.
⚠
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.
⚠
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.
(open, inline)
Self::is_subset(other, self)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
⚠
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.
(open)
pearlite! { 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.
(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.
(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.
(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.
⚠
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.
(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.
(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.
(open)
pearlite! { if n == 0 { proof_assert! { forall<xs: Seq<T>> xs.len() == 0 ==> xs == Seq::empty() }; FSet::singleton(Seq::empty()) } else { proof_assert! { forall<xs: Seq<T>, i> 0 < i && i < xs.len() ==> xs[i] == xs.tail()[i-1] }; FSet::cons(self, self.replicate(n - 1)) } }
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.
(open)
pearlite! { 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))
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_contracts::{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_contracts::{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_contracts::{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 insert_ghost_unsized(&mut self, value: Box<T>) -> bool
pub fn insert_ghost_unsized(&mut self, value: Box<T>) -> bool
Same as Self::insert_ghost, but for unsized values.
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_contracts::{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_contracts::{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()