Skip to content

Commit a4ac54b

Browse files
authored
document snapshot equality (viperproject#1137)
1 parent 2190fd2 commit a4ac54b

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

docs/user-guide/src/syntax.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Prusti specifications are a superset of Rust boolean expressions. They must be d
66
| --- | --- |
77
| [`old(...)`](#old-expressions) | Value of expression in a previous state |
88
| [`... ==> ...`](#implications) | Implication |
9+
| [`... === ...`](#snapshot-equality) | Snapshot equality |
910
| [`forall(...)`](#quantifiers) | Universal quantifier |
1011
| [`exists(...)`](#quantifiers) | Existential quantifier |
1112
| [<code>... &#x7C;= ...</code>](#specification-entailments) | Specification entailment |
@@ -14,7 +15,7 @@ Prusti specifications are a superset of Rust boolean expressions. They must be d
1415

1516
Old expressions are used to refer to the value that a memory location pointed at by a mutable reference had at the beginning of the function:
1617

17-
```rust
18+
```rust,noplaypen
1819
use prusti_contracts::*;
1920
2021
#[ensures(*x == old(*x) + 1)]
@@ -27,7 +28,7 @@ pub fn inc(x: &mut u32) {
2728

2829
Implications express a [relationship](https://en.wikipedia.org/wiki/Material_conditional) between two boolean expressions:
2930

30-
```rust
31+
```rust,noplaypen
3132
#[pure]
3233
#[ensures(result ==> self.len() == 0)]
3334
#[ensures(!result ==> self.len() > 0)]
@@ -36,17 +37,41 @@ pub fn is_empty(&self) -> bool;
3637

3738
There is no syntax for logical equivalences ("if and only if"), because this coincides with `==`:
3839

39-
```rust
40+
```rust,noplaypen
4041
#[pure]
4142
#[ensures(result == (self.len() == 0))]
4243
pub fn is_empty(&self) -> bool;
4344
```
4445

46+
## Snapshot Equality
47+
48+
Snapshot equality (`===`) compares the
49+
[snapshots](https://viperproject.github.io/prusti-dev/dev-guide/encoding/types-snap.html)
50+
of two values; essentially checking if the two values are structurally equal. In
51+
contrast, the standard equality (`==`) between values is determined by the
52+
implementation of
53+
[`PartialEq`](https://doc.rust-lang.org/std/cmp/trait.PartialEq.html). These two
54+
equalities do not necessarily coincide. For example, some types do not implement
55+
`PartialEq`, or their implementation cannot be encoded as a pure function.
56+
Nonetheless, snapshot equality could be used to compare values of such types, as
57+
in the following code:
58+
59+
```rust,noplaypen
60+
#[requires(a === b)]
61+
fn foo<T>(a: T, b: T) {}
62+
63+
struct X { a: i32 }
64+
65+
fn main() {
66+
foo(X { a: 1 }, X { a: 1 });
67+
}
68+
```
69+
4570
## Quantifiers
4671

4772
Quantifiers are typically used for describing how a method call changes a container such as a vector:
4873

49-
```rust
74+
```rust,noplaypen
5075
#[requires(0 <= index && index < self.len())]
5176
#[ensures(self.len() == old(self.len()))]
5277
#[ensures(self.lookup(index) == value)]

0 commit comments

Comments
 (0)