InvCell

Struct InvCell 

Source
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> InvCell<T, Pred>

Source

pub closed spec fn predicate(&self) -> Pred

Source§

impl<T, Pred: Predicate<T>> InvCell<T, Pred>

Source

pub open spec fn inv(&self, val: T) -> bool

{ self.predicate().predicate(val) }
Source

pub exec fn new(val: T, Ghost(pred): Ghost<Pred>) -> cell : Self

requires
pred.predicate(val),
ensures
cell.predicate() == pred,
Source

pub exec fn set(&self, val: T)

requires
self.inv(val),
Source

pub exec fn replace(&self, val: T) -> old_val : T

requires
self.inv(val),
ensures
self.inv(old_val),
Source

pub exec fn get(&self) -> val : T
where T: Copy,

ensures
self.inv(val),
Source

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>
where T: Unpin, Pred: Unpin,

§

impl<T, Pred> UnwindSafe for InvCell<T, Pred>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: From<T>,

Source§

exec fn obeys_from_spec() -> bool

Source§

exec fn from_spec(v: T) -> VERUS_SPEC__A

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: Into<T>,

Source§

exec fn obeys_into_spec() -> bool

Source§

exec fn into_spec(self) -> T

Source§

impl<T, U> IntoSpecImpl<U> for T
where U: From<T>,

Source§

open spec fn obeys_into_spec() -> bool

{ <U as FromSpec<Self>>::obeys_from_spec() }
Source§

open spec fn into_spec(self) -> U

{ U::from_spec(self) }
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: TryFrom<T>,

Source§

exec fn obeys_try_from_spec() -> bool

Source§

exec fn try_from_spec( v: T, ) -> Result<VERUS_SPEC__A, <VERUS_SPEC__A as TryFrom<T>>::Error>

Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__A
where VERUS_SPEC__A: TryInto<T>,

Source§

exec fn obeys_try_into_spec() -> bool

Source§

exec fn try_into_spec(self) -> Result<T, <VERUS_SPEC__A as TryInto<T>>::Error>

Source§

impl<T, U> TryIntoSpecImpl<U> for T
where U: TryFrom<T>,

Source§

open spec fn obeys_try_into_spec() -> bool

{ <U as TryFromSpec<Self>>::obeys_try_from_spec() }
Source§

open spec fn try_into_spec(self) -> Result<U, <U as TryFrom<T>>::Error>

{ <U as TryFromSpec<Self>>::try_from_spec(self) }