Skip to content

Commit 32e7468

Browse files
committed
Consider Pattern Type style
Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent 7d0d342 commit 32e7468

File tree

1 file changed

+15
-20
lines changed

1 file changed

+15
-20
lines changed

rfc/src/rfcs/0010-quantifiers.md

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,30 @@
88

99
## Summary
1010

11-
Quantifiers are like logic-level loops and a powerful reasoning helper, which allow us to express statements about objects in a domain that satisfy a given condition. There are two primary quantifiers: the existential quantifier (∃) and the universal quantifier (∀).
11+
Quantifiers are logical operators that allow users to express that a property or condition applies to some or all objects within a given domain.
1212

13-
1. The existential quantifier (∃): represents the statement "there exists." We use to express that there is at least one object in the domain that satisfies a given condition. For example, "∃x P(x)" means "there exists an x such that P(x) is true."
13+
## User Impact
1414

15-
2. The universal quantifier (∀): represents the statement "for all" or "for every." We use it to express that a given condition is true for every object in the domain. For example, "∀x P(x)" means "for every x, P(x) is true."
15+
There are two primary quantifiers: the existential quantifier (∃) and the universal quantifier (∀).
1616

17-
## User Impact
17+
1. The existential quantifier (∃): represents the statement "there exists." We use to express that there is at least one object in the domain that satisfies a given condition. For example, "∃x P(x)" means "there exists a value x such that P(x) is true."
18+
19+
2. The universal quantifier (∀): represents the statement "for all" or "for every." We use it to express that a given condition is true for every object in the domain. For example, "∀x P(x)" means "for every value x, P(x) is true."
1820

19-
Quantifiers enhance users' expressive capabilities, enabling the verification of more intricate properties in a concise manner.
2021
Rather than exhaustively listing all elements in a domain, quantifiers enable users to make statements about the entire domain at once. This compact representation is crucial when dealing with large or unbounded inputs. Quantifiers also facilitate abstraction and generalization of properties. Instead of specifying properties for specific instances, quantified properties can capture general patterns and behaviors that hold across different objects in a domain. Additionally, by replacing loops in the specification with quantifiers, Kani can encode the properties more efficiently within the specified bounds, making the verification process more manageable and computationally feasible.
2122

2223
This new feature doesn't introduce any breaking changes to users. It will only allow them to write properites using the existential (∃) and universal (∀) quantifiers.
2324

2425
## User Experience
2526

26-
We propose a syntax inspired by [Prusti](https://viperproject.github.io/prusti-dev/user-guide/syntax.html?highlight=quanti#quantifiers). Quantifiers must have only one bound variable (restriction imposed today by CBMC). The syntax of existential (i.e., `kani::exists`) and universal (i.e., `kani::forall`) quantifiers are:
27-
28-
```rust
29-
kani::exists(|<bound variable>: <bound variable type>| <range> && <Boolean expression>)
30-
kani::forall(|<bound variable>: <bound variable type>| <range> ==> <Boolean expression>)
31-
```
32-
33-
where `<range>` is an expression of the form
27+
We propose a syntax inspired by ["Pattern Types"](https://github.com/rust-lang/rust/pull/120131). The syntax of existential (i.e., `kani::exists`) and universal (i.e., `kani::forall`) quantifiers are:
3428

3529
```rust
36-
<lower bound> <= <bound variable> && <bound variable> < <upper bound>
30+
kani::exists(|<var>: <type> is <range-expr> | <boolean-expression>)
31+
kani::forall(|<var>: <type> is <range-expr> | <boolean-expression>)
3732
```
3833

39-
where `lower bound` and `upper bound` are constants. The bound predicates could be strict (e.g., `<lower bound> < <bound variable>`), or non-strict (e.g., `<upper bound> <= <bound variable>`), but both the bounds must be **constants**. CBMC's SAT backend only supports bounded quantification under **constant** lower and upper bounds.
34+
CBMC's SAT backend only supports bounded quantification under **constant** lower and upper bounds (for more details, see the [documentation for quantifiers in CBMC](https://diffblue.github.io/cbmc/contracts-quantifiers.html)). In contracts, the SMT backend supports arbitrary Boolean expressions.
4035

4136
Consider the following example adapted from the documentation for the [from_raw_parts](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.from_raw_parts) function:
4237

@@ -117,7 +112,7 @@ use std::mem;
117112
fn main() {
118113
let original_v = vec![kani::any::<usize>(); 3];
119114
let v = original_v.clone();
120-
kani::assume(kani::forall(|i: usize| (i < v.len()) ==> (v[i] < 5)));
115+
kani::assume(kani::forall(|i: usize is ..v.len() | v[i] < 5));
121116

122117
// Prevent running `v`'s destructor so we are in complete control
123118
// of the allocation.
@@ -136,7 +131,7 @@ fn main() {
136131

137132
// Put everything back together into a Vec
138133
let rebuilt = Vec::from_raw_parts(p, len, cap);
139-
assert!(kani::forall(|i: usize| (i < len) ==> (rebuilt[i] == original_v[i]+1)));
134+
assert!(kani::forall(|i: usize is ..len | rebuilt[i] == original_v[i]+1));
140135
}
141136
}
142137
```
@@ -151,7 +146,7 @@ use std::mem;
151146
fn main() {
152147
let original_v = vec![kani::any::<usize>(); 3];
153148
let v = original_v.clone();
154-
kani::assume(kani::forall(|i: usize| (i < v.len()) ==> (v[i] < 5)));
149+
kani::assume(kani::forall(|i: usize is ..v.len() | v[i] < 5));
155150

156151
// Prevent running `v`'s destructor so we are in complete control
157152
// of the allocation.
@@ -173,7 +168,7 @@ fn main() {
173168

174169
// Put everything back together into a Vec
175170
let rebuilt = Vec::from_raw_parts(p, len, cap);
176-
assert!(kani::exists(|i: usize| (i < len) && (rebuilt[i] == 0)));
171+
assert!(kani::exists(|i: usize is ..len | rebuilt[i] == 0));
177172
}
178173
}
179174
```
@@ -202,6 +197,6 @@ Kani should have the same support that CBMC has for quantifiers with its SAT bac
202197
## Future possibilities
203198

204199
<!-- For Developers -->
205-
- CBMC has an SMT backend which allow the use of quantifiers with arbitrary Boolean expressions. Kani must include an option for users to experiment with this backend.
200+
- CBMC has an SMT backend which allows the use of quantifiers with arbitrary Boolean expressions. Kani must include an option for users to experiment with this backend.
206201

207202
---

0 commit comments

Comments
 (0)