Skip to content

Commit b5da991

Browse files
authored
Organize reference pages for prover modes (#2613)
1 parent 8756286 commit b5da991

13 files changed

Lines changed: 259 additions & 65 deletions

source/docs/guide/src/SUMMARY.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,21 @@
157157
- [The `is` operator](./reference-is.md)
158158
- [The `matches` operator](./reference-matches.md)
159159
- [`decreases_to!`](./reference-decreases-to.md)
160-
- [Proof features]()
161-
- [assert and assume]()
162-
- [assert ... by](./reference-assert-by.md)
163-
- [assert forall ... by](./reference-assert-forall-by.md)
164-
- [assert ... by(bit_vector)](./reference-assert-by-bit-vector.md)
165-
- [assert ... by(nonlinear_arith)](./reference-assert-by-nonlinear.md)
166-
- [assert ... by(compute) / by(compute_only)](./reference-assert-by-compute.md)
167-
- [reveal, reveal_with_fuel, hide](./reference-reveal-hide.md)
168-
- [reveal_strlit](./reference-reveal-strlit.md)
160+
- [Proofs]()
161+
- [Proof statements]()
162+
- [assert](./reference-assert.md)
163+
- [assume](./reference-assume.md)
164+
- [assert ... by](./reference-assert-by.md)
165+
- [assert forall ... by](./reference-assert-forall-by.md)
166+
- [assert ... by(...)](./reference-assert-by-prover.md)
167+
- [reveal, reveal_with_fuel, hide](./reference-reveal-hide.md)
168+
- [reveal_strlit](./reference-reveal-strlit.md)
169+
- [Prover modes]()
170+
- ["default" mode]()
171+
- [`bit_vector`](./reference-prover-mode-bit-vector.md)
172+
- [`nonlinear`](./reference-prover-mode-nonlinear.md)
173+
- [`integer_ring`](./reference-prover-mode-integer-ring.md)
174+
- [`compute`/`compute_only`](./reference-prover-mode-compute.md)
169175
- [Function specifications]()
170176
- [Function Signatures]()
171177
- [Exec fn signature](./reference-exec-signature.md)

source/docs/guide/src/external_trait_specifications.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ for this purpose:
99

1010
## Soundness warning
1111

12-
**Be cautious when adding specifications to external traits.** All implementations
13-
of the trait — including those in unverified code, even code that hasn't been written yet — are
14-
assumed to uphold the specification. For example, if you verify a crate with
15-
`pub fn test<A: Formatter>(...)`, Verus assumes that whatever type instantiates `A` will
16-
satisfy the `Formatter` specification, even if that type comes from an unverified crate.
17-
This is a contract on both current and future unverified code.
18-
19-
[See below](#the-obeys_-pattern-in-vstd) for a useful pattern (employed by `vstd`) for mitigating this soundness risk.
12+
> [!CAUTION]
13+
> Since the `assume_specification` statement is unchecked, it can easily be used to subvert
14+
> Verus's guarantees.
15+
>
16+
> Further, specifying traits correctly is often even more difficult than specifying ordinary
17+
> functions.
18+
>
19+
> All implementations
20+
> of the trait — including those in unverified code, even code that hasn't been written yet — are
21+
> assumed to uphold the specification. For example, if you verify a crate with
22+
> `pub fn test<A: Formatter>(...)`, Verus assumes that whatever type instantiates `A` will
23+
> satisfy the `Formatter` specification, even if that type comes from an unverified crate.
24+
> This is a contract on both current and future unverified code.
25+
>
26+
> [See below](#the-obeys_-pattern-in-vstd) for a useful pattern (employed by `vstd`) for mitigating this soundness risk.
2027
2128
## Basic external trait specification
2229

source/docs/guide/src/reference-assert-by-nonlinear.md

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# assert ... by(...)
2+
3+
The `assert ... by` statement is used to invoke a specialized _prover mode_ for proving
4+
the given assertion.
5+
6+
### Syntax
7+
8+
We divide the prover modes into "solver modes" (which invoke a solver) and "interpreter modes" (which invoke the interpreter).
9+
10+
```verus-grammar
11+
V@[assert_by_prover_stmt] ::=
12+
assert ( V@[spec_expr] ) by ( V@[assert_by_solver_mode] ) V@[assert_by_prover_requires]? ;
13+
| assert ( V@[spec_expr] ) by ( V@[assert_by_interpreter_mode] );
14+
15+
V@[assert_by_solver_mode] ::= nonlinear_arith | bit_vector;
16+
V@[assert_by_interpreter_mode] ::= compute | compute_only;
17+
18+
V@[assert_by_prover_requires] ::=
19+
requires (V@[spec_expr],)+
20+
```
21+
22+
> [!NOTE]
23+
> At present, the [`integer_ring`](./reference-prover-mode-integer-ring.md) prover mode may only
24+
> be used in a [proof function declaration](./reference-proof-signature.md),
25+
> not in an assert-by.
26+
27+
### Proof operation
28+
29+
**Solver modes.**
30+
For `nonlinear_arith` and `bit_vector` modes,
31+
Verus attempts to prove the given predicate via the specified solver
32+
(the [`nonlinear_arith` solver](./reference-prover-mode-nonlinear.md)
33+
or the [`bit_vector` solver](./reference-prover-mode-bit-vector.md)).
34+
The predicate is proved in isolation, absent any surrounding context.
35+
36+
Specifically, for a statement
37+
<code>assert ( Q ) by ( V@[assert_by_solver_mode] )</code>,
38+
Verus tries to prove `Q` using the solver, and then assumes `Q` for the subsequent code.
39+
40+
If a `requires P` clause is additionally provides, then Verus:
41+
42+
* Proves `P` using the default solver (with full context available)
43+
* Proves `P ==> Q` using the specified solver (in isolation)
44+
* And finally assumes `Q` for subsequent code.
45+
46+
**Interpreter modes.**
47+
For `compute` and `compute_only` modes, Verus uses its [specification interpreter](./reference-prover-mode-compute.md) to simplify the expression `Q` as much as possible, yielding an expression `Q'`.
48+
49+
* For `compute_only`, Verus will check that `Q'` is the boolean value `true`, and then assumes
50+
the given predicate for all subsequent code.
51+
* For `compute`, Verus will replace the assert-by statement with `assert(Q')`, which then behaves
52+
like an ordinary [`assert`](./reference-assert.md).
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# `assert`
2+
3+
### Syntax
4+
5+
```verus-grammar
6+
V@[assert] ::= assert (V@[spec_expr]) ;
7+
```
8+
9+
### Proof operation
10+
11+
Prove the given expression using the default solver, and then assume the predicate for
12+
subsequence code.

source/docs/guide/src/reference-assume-specification.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# assume_specification
22

3+
> [!CAUTION]
4+
> Since the `assume_specification` statement is unchecked, it can easily be used to subvert
5+
> Verus's guarantees.
6+
>
7+
> Be sure to read our [advice on interacting with unverified code](./interacting-with-unverified-code.md).
8+
39
The `assume_specification` directive tells Verus to use the given specification for the given function.
410
Verus assumes that this specification holds **without proof**.
511

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# `assume`
2+
3+
<!-- TODO: Should decide whether or not the presence of an assume still gives guarantees about the subset of program executions where the assumption holds. -->
4+
5+
> [!CAUTION]
6+
> Since the `assume` statement is unchecked, it can easily be used to subvert Verus's guarantees.
7+
> In particular, successful "verification" by Verus provides **no guarantees** on the program
8+
> if it includes any `assume` statements, unless those `assume` statements could in principle
9+
> be replaced by a successful `assert` statement.
10+
>
11+
> The `assume` statement is most useful during _intermediate_ stages of development,
12+
> e.g., within an [assert/assume-driven proof-development process](./assert_assume.md).
13+
14+
> [!TIP]
15+
> The `--no-cheating` flag can be used to disallow `assume` statements.
16+
17+
### Syntax
18+
19+
```verus-grammar
20+
V@[assume] ::= assume (V@[spec_expr]) ;
21+
```
22+
23+
### Proof operation
24+
25+
Assume the given predicate without proof.

source/docs/guide/src/reference-proof-signature.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ The general form of a `proof` function signature takes the form:
66
V@[proof_fn_item] ::= V@[proof_fn_proved] | V@[proof_fn_axiom]
77
88
V@[proof_fn_proved] ::=
9-
R@[visibility]? broadcast? proof fn R@[function_name] R@[generics]?(R@[args...]) ( -> V@[proof_return_type] )?
9+
R@[visibility]? broadcast? proof fn R@[function_name] R@[generics]?(R@[args...]) ( by(function_prover_mode) )? ( -> V@[proof_return_type] )?
1010
R@[where_clause]?
1111
V@[requires_clause]?
1212
V@[ensures_clause]?
@@ -25,6 +25,8 @@ V@[proof_fn_axiom] ::=
2525
V@[decreases_clause]?
2626
;
2727
28+
V@[function_prover_mode] ::= integer_ring | bit_vector | nonlinear_arith
29+
2830
V@[proof_return_type] ::= V@[proof_return_type_named] | V@[proof_return_type_anon]
2931
V@[proof_return_type_named] ::= ( tracked? R@[pattern] : R@[type] )
3032
V@[proof_return_type_anon] ::= R@[type]
@@ -54,3 +56,10 @@ All arguments and return values need to have `ghost` or `tracked` mode.
5456
Arguments are `ghost` by default, and they can be declared `tracked` with the `tracked` keyword.
5557

5658
See [here](./reference-var-modes.md#cheat-sheet) for more information.
59+
60+
## Function prover mode
61+
62+
If the V@[function_prover_mode] is provided, the proof is dispatched via the given solver
63+
([`integer_ring`](./reference-prover-mode-integer-ring.md),
64+
[`bit_vector`](./reference-prover-mode-bit-vector.md),
65+
or [`nonlinear_arith`](./reference-prover-mode-nonlinear.md)).

source/docs/guide/src/reference-assert-by-bit-vector.md renamed to source/docs/guide/src/reference-prover-mode-bit-vector.md

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,38 @@
1-
# assert ... by(bit_vector)
1+
# The `bit_vector` prover mode
22

3-
Invoke Verus's bitvector solver to prove the given predicate.
4-
This is particularly useful for bitwise operators
5-
and integer arithmetic on finite-width integers.
6-
Internally, the solver uses a technique called _bit-blasting_, which represents each numeric variable
7-
by its binary representation as a bit vector, and every operation as a boolean circuit.
3+
> [!TIP]
4+
> See the [guide page](./bitvec.md) for practical tips on using the `bit_vector` solver.
85
6+
### Methods of invocation
97

8+
**By assertion.**
9+
The `bit_vector` solver can be invoked via an [`assert-by` statement](./reference-assert-by-prover.md):
10+
11+
```
12+
assert(Q) by(bit_vector);
1013
```
11-
assert(P) by(bit_vector);
14+
15+
Proves `Q` via the the `bit_vector` solver.
16+
1217
```
18+
assert(Q) by(bit_vector) requires P;
19+
```
20+
21+
Proves `P ==> Q` via the the `bit_vector` solver.
22+
23+
**As a proof function.**
24+
The `bit_vector` solver can be invoked with a `by(bit_vector)` on a [proof function](./reference-proof-signature.md).
1325

1426
```
15-
assert(P) by(bit_vector)
16-
requires Q;
27+
proof fn example(...) by(bit_vector)
28+
requires P
29+
ensures Q
30+
{ }
1731
```
1832

19-
The prover does not have access to any prior context except that which is given in
20-
the `requires` clause, if provided. If the `requires` clause is provided, then the
21-
bit vector solver attempts to prove `Q ==> P`. Verus will also check (using its normal solver)
22-
that `Q` holds from the prior proof context.
33+
This proves `P ==> Q` via the `bit_vector` solver.
2334

24-
The expressions `P` and `Q` may only contain expressions that the bit solver understands.
25-
This includes:
35+
### Supported predicates
2636

2737
* Variables of type `bool` or finite-width integer types (`u64`, `i64`, `usize`, etc.)
2838
* All free variables are treated symbolically. Even if a variable is defined via a `let`
@@ -36,16 +46,17 @@ This includes:
3646
* Boolean operators (`&&`, `||`, `^`) and conditional expressions
3747
* The `usize::BITS` constant
3848

39-
## Internal operation
49+
## Solver operation
4050

4151
Verus's bitvector solver encodes the expression by representing all integers using an SMT "bitvector" type.
4252
Most of the above constraints arise
4353
because of the fact that Verus has to choose a fixed bitwidth for any given expression.
4454

4555
Note that, although the bitvector solver cannot handle free variables of type
46-
`int` or `nat`, it _can_ handle other kinds of expressions that are typed `int` or `nat`.
56+
`int` or `nat`, it _can_ handle some expressions that are typed `int` or `nat` provided
57+
Verus can bound the the bitwidth needed to represent the number.
4758
For example, if `x` and `y` have type `u64`, then `x + y` has type `int`,
48-
but the Verus bitvector solver knows that `x + y` is representable with 65 bits.
59+
but the Verus knows that `x + y` is representable with 65 bits.
4960

5061
### Handling `usize` and `isize`
5162

source/docs/guide/src/reference-assert-by-compute.md renamed to source/docs/guide/src/reference-prover-mode-compute.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1-
# assert ... by(compute) / by(compute_only)
1+
# The compute mode
22

3-
See [this section of the tutorial](./assert_by_compute.md) for motivation and an example.
3+
> [!TIP]
4+
> See the [guide page](./assert_by_compute.md) for practical tips on using this feature.
45
5-
A statement of the form:
6+
### Methods of invocation
67

8+
**By assertion.**
9+
The `nonlinear_arith` solver can be invoked via an [`assert-by` statement](./reference-assert-by-prover.md):
10+
11+
```
12+
assert(Q) by(compute_only);
713
```
8-
assert(P) by(compute_only);
14+
15+
Proves `Q` by simplifying it via the interpreter and checking
16+
if the result is the boolean value `true`.
17+
918
```
19+
assert(Q) by(compute);
20+
```
21+
22+
Proves `Q` by simplifying it via the interpreter to an expression `Q'` and replacing
23+
the statement with `assert(Q);`.
24+
25+
### Interpreter operation
1026

11-
Will evaluate the expression `P` as far a possible, and Verus accepts the result if it
12-
evaluates to the boolean expression `true`. It unfolds function definitions and evaluates
27+
The interpreter unfolds function definitions and evaluates
1328
arithmetic expressions. It is capable of some symbolic manipulation, but it does not handle
1429
algebraic laws like `a + b == b + a`, and it works best when evaluating constant expressions.
1530

@@ -27,7 +42,7 @@ to finish the problem through the normal solver. So for example, if after expans
2742
`P` results in a trivial expression like `a+b == b+a`, then it should be solved
2843
with `by(compute)`.
2944

30-
### Memoization
45+
### Configurating the evaluation strategy
3146

3247
The [`#[verifier::memoize]` attribute](./reference-attributes.md#verifiermemoize) can be used to mark
3348
certain functions for [memoizing](https://en.wikipedia.org/wiki/Memoization).

0 commit comments

Comments
 (0)