Skip to main content

Invariant

Trait Invariant 

Source
pub trait Invariant {
    // Required method
    fn invariant(self) -> bool;
}
Expand description

A user-defined type invariant.

Type invariants are additional pre- and postconditions added to each program functions.

Not to be confused with loop invariants or resource invariants.

§Example

struct SumTo10 {
    a: i32,
    b: i32,
}
// The type invariant constrains the set of valid `SumTo10`s to
// only allow values where the sum of both fields is equal to 10.
impl Invariant for SumTo10 {
    #[logic(open)]
    fn invariant(self) -> bool {
        pearlite! {
            self.a@ + self.b@ == 10
        }
    }
}

// #[requires(inv(x))]     // generated by Creusot
// #[ensures(inv(result))] // generated by Creusot
fn invariant_holds(mut x: SumTo10) -> SumTo10 {
    assert!(x.a + x.b == 10); // We are given the invariant when entering the function
    x.a = 5; // we can break it locally!
    x.b = 5; // but it must be restored eventually
    x
}

§Structural invariants

A type automatically inherits the invariants of its fields.

Examples:

  • x: (T, U) -> inv(x.0) && inv(x.1)
  • x: &T -> inv(*x)
  • x: Vec<T> -> forall<i> 0 <= i && i < x@.len() ==> inv(x@[i])

This does not prevent the type to additionnaly implement the Invariant trait.

§Mutable borrows

For mutable borrows, the invariant is the conjunction of the invariants of the current and final values: x: &mut T -> inv(*x) && inv(^x).

§Logical functions

Invariant pre- and postconditions are not added to logical functions:

#[logic]
#[ensures(x.a@ + x.b@ == 10)]
fn not_provable(x: SumTo10) {}

Required Methods§

Source

fn invariant(self) -> bool

logic(prophetic)

Implementations on Foreign Types§

Source§

impl<A: Iterator, B: Iterator> Invariant for Zip<A, B>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.itera()) && inv(self.iterb())

Source§

impl<B, I: Iterator, F: FnMut(I::Item) -> Option<B>> Invariant for FilterMap<I, F>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter()) && inv(self.func()) && private_invariant(self)
Source§

impl<I> Invariant for Cloned<I>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter())

Source§

impl<I> Invariant for Copied<I>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter())

Source§

impl<I> Invariant for Rev<I>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter())

Source§

impl<I: IteratorSpec> Invariant for Enumerate<I>

Source§

fn invariant(self) -> bool

logic(prophetic)

ensures

result ==> inv(self.iter())

Source§

impl<I: IteratorSpec, B, F: FnMut(I::Item) -> B> Invariant for Map<I, F>

Source§

fn invariant(self) -> bool

logic(prophetic)

ensures

result ==> inv(self.iter()) && inv(self.func())

Source§

impl<I: Iterator> Invariant for Fuse<I>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.view())

Source§

impl<I: Iterator> Invariant for Skip<I>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter())

Source§

impl<I: Iterator> Invariant for Take<I>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter())

Source§

impl<I: Iterator, F: FnMut(&I::Item) -> bool> Invariant for Filter<I, F>

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(self.iter()) && inv(self.func()) && private_invariant(self)

ensures

result ==> inv(self.iter()) && inv(self.func())

Source§

impl<T> Invariant for [T]

Source§

fn invariant(self) -> bool

logic(open, prophetic)

inv(self@)

Source§

impl<T, A: Allocator> Invariant for VecDeque<T, A>

Available on crate feature nightly only.
Source§

fn invariant(self) -> bool

logic(open, prophetic)

inv(self@)

Source§

impl<T, A: Allocator> Invariant for Vec<T, A>

Available on crate feature nightly only.
Source§

fn invariant(self) -> bool

logic(open, prophetic)

inv(self@)

Source§

impl<T, const N: usize> Invariant for [T; N]

Source§

fn invariant(self) -> bool

logic(open, prophetic)

inv(self@) && self@.len() == N@

Source§

impl<T: ?Sized> Invariant for &T

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(*self)

Source§

impl<T: ?Sized> Invariant for &mut T

Source§

fn invariant(self) -> bool

logic(open, prophetic, inline)

inv(*self) && inv(^self)

Source§

impl<T: ?Sized, A: Allocator> Invariant for Box<T, A>

Available on crate feature nightly only.
Source§

fn invariant(self) -> bool

logic(open, prophetic)

inv(*self)

Implementors§

Source§

impl<I: IteratorSpec, B, F: FnMut(I::Item, Snapshot<Seq<I::Item>>) -> B> Invariant for MapInv<I, F>

Source§

impl<K, V> Invariant for FMap<K, V>

Source§

impl<R: UnitRA> Invariant for Authority<R>

Source§

impl<T> Invariant for Seq<T>

Source§

impl<T> Invariant for SeqIterRef<'_, T>

Source§

impl<T> Invariant for FSet<T>

Source§

impl<T: Sized> Invariant for Perm<PermCell<T>>

Source§

impl<T: ?Sized> Invariant for Perm<*const T>

Source§

impl<T: ?Sized> Invariant for Ghost<T>