pub struct InvCell<T, Pred> { /* private fields */ }Expand description
Verus’s closest analogue of Cell.
An InvCell always allows reading and writing, even through a shared reference.
To reason about the value in an InvCell, the client must specify an “invariant predicate”
to constrain the allowed values.
§Examples
On construction of an InvCell, we can specify an invariant for the object that goes inside.
One way to do this is by providing a spec_fn, which implements the Predicate trait.
ⓘ
fn example1() {
// We can create a cell with an invariant: `v == 5 || v == 13`.
// Thus only 5 or 13 can be stored in the cell.
let cell = InvCell::<u64, spec_fn(u64) -> bool>::new(5, Ghost(|v| v == 5 || v == 13));
let ref1 = &cell;
let ref2 = &cell;
let x = ref1.get();
assert(x == 5 || x == 13);
ref1.set(13);
let y = ref2.get();
assert(y == 5 || y == 13);
}It’s often easier to implement the Predicate trait yourself. This way you can
have a configurable predicate without needing to work with higher-order functions.
ⓘ
pub struct FixedParity {
pub parity: int,
}
impl Predicate<u64> for FixedParity {
open spec fn predicate(&self, v: u64) -> bool {
v % 2 == self.parity
}
}
fn example2() {
// Create a cell that can only store even integers
let cell_even = InvCell::<u64, FixedParity>::new(20, Ghost(FixedParity { parity: 0 }));
// Create a cell that can only store odd integers
let cell_odd = InvCell::<u64, FixedParity>::new(23, Ghost(FixedParity { parity: 1 }));
let x = cell_even.get();
assert(x % 2 == 0);
let y = cell_odd.get();
assert(y % 2 == 1);
}Implementations§
Source§impl<T, Pred: Predicate<T>> InvCell<T, Pred>
impl<T, Pred: Predicate<T>> InvCell<T, Pred>
Sourcepub exec fn new(val: T, Ghost(pred): Ghost<Pred>) -> cell : Self
pub exec fn new(val: T, Ghost(pred): Ghost<Pred>) -> cell : Self
requires
pred.predicate(val),ensurescell.predicate() == pred,Sourcepub exec fn replace(&self, val: T) -> old_val : T
pub exec fn replace(&self, val: T) -> old_val : T
requires
self.inv(val),ensuresself.inv(old_val),Sourcepub exec fn into_inner(self) -> val : T
pub exec fn into_inner(self) -> val : T
ensures
self.inv(val),Auto Trait Implementations§
impl<T, Pred> !Freeze for InvCell<T, Pred>
impl<T, Pred> !RefUnwindSafe for InvCell<T, Pred>
impl<T, Pred> Send for InvCell<T, Pred>where
T: Send,
impl<T, Pred> !Sync for InvCell<T, Pred>
impl<T, Pred> Unpin for InvCell<T, Pred>
impl<T, Pred> UnwindSafe for InvCell<T, Pred>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
Source§impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryFrom<T>,
impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryFrom<T>,
Source§exec fn obeys_try_from_spec() -> bool
exec fn obeys_try_from_spec() -> bool
Source§impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryInto<T>,
impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryInto<T>,
Source§exec fn obeys_try_into_spec() -> bool
exec fn obeys_try_into_spec() -> bool
Source§impl<T, U> TryIntoSpecImpl<U> for Twhere
U: TryFrom<T>,
impl<T, U> TryIntoSpecImpl<U> for Twhere
U: TryFrom<T>,
Source§open spec fn obeys_try_into_spec() -> bool
open spec fn obeys_try_into_spec() -> bool
{ <U as TryFromSpec<Self>>::obeys_try_from_spec() }