A useful tool to have in proofs is the Snapshot<T>
type (creusot_contracts::Snapshot
). Snapshot<T>
is:
- a zero-sized-type
- created with the
snapshot!
macro - whose model is the model of
T
- that can be dereferenced in a logic context.
They can be useful if you need a way to remember a previous value, but only for the proof:
#[ensures(array@.permutation_of((^array)@))]
#[ensures(sorted((^array)@))]
pub fn insertion_sort(array: &mut [i32]) {
let original = snapshot!(*array); // remember the original value
let n = array.len();
#[invariant(original@.permutation_of(array@))]
#[invariant(...)]
for i in 1..n {
let mut j = i;
#[invariant(original@.permutation_of(array@))]
#[invariant(...)]
while j > 0 {
if array[j - 1] > array[j] {
array.swap(j - 1, j);
} else {
break;
}
j -= 1;
}
}
proof_assert!(sorted_range(array@, 0, array@.len()));
}
#[logic]
fn permutation_of(s1: Seq<i32>, s2: Seq<i32>) -> bool {
// ...
}
#[logic]
fn is_sorted(s: Seq<i32>) -> bool {
// ...
}