Skip to content

Commit 914bedd

Browse files
committed
Explain annotation and configuration in README
1 parent a4ef1f5 commit 914bedd

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,64 @@ safe
6666

6767
Integration test examples are located under `tests/ui/` and can be executed using `cargo test`. You can review these examples to understand what the current Thrust implementation can handle.
6868

69+
## Annotation
70+
71+
Thrust can verify a wide range of programs without explicit annotations, but you can use `#[thrust::requires(expr)]` and `#[thrust::ensures(expr)]` to annotate the precondition and postcondition of a function, aiding in verification or specifying the specification. Here, `expr` is a logical expression that supports basic integer, boolean, and reference operations.
72+
73+
```rust
74+
#[thrust::requires(n >= 0)]
75+
#[thrust::ensures((result * 2) == n * (n + 1))]
76+
fn sum(n: i32) -> i32 {
77+
if n == 0 {
78+
0
79+
} else {
80+
n + sum(n - 1)
81+
}
82+
}
83+
```
84+
85+
You can use the `^` unary operator to denote the value of a mutable reference after the function is called. Note that in the current implementation, you need to specify both `requires` and `ensures` when using either one.
86+
87+
```rust
88+
#[thrust::requires(true)]
89+
#[thrust::ensures(^ma == *ma + a)]
90+
fn add(ma: &mut i32, a: i32) {
91+
*ma += a;
92+
}
93+
```
94+
95+
The conditions on `thrust::requires` and `thrust::ensures` are internally encoded as refinement types for the parameter and return types. You can also specify these refinement types directly using `#[thrust::param(param: type)]` and `#[thrust::ret(type)]`.
96+
97+
```rust
98+
#[thrust::param(n: { x: int | x >= 0 })]
99+
#[thrust::ret({ x: int | (x * 2) == n * (n + 1) })]
100+
fn sum(n: i32) -> i32 {
101+
if n == 0 {
102+
0
103+
} else {
104+
n + sum(n - 1)
105+
}
106+
}
107+
```
108+
109+
The bodies of functions marked with `#[thrust::trusted]` are not analyzed by Thrust. Additionally, `#[thrust::callable]` is an alias for `#[thrust::requires(true)]` and `#[thrust::ensures(true)]`.
110+
111+
```rust
112+
#[thrust::trusted]
113+
#[thrust::callable]
114+
fn rand() -> i32 { unimplemented!() }
115+
```
116+
117+
## Configuration
118+
119+
Several environment variables are used by Thrust to configure its behavior:
120+
121+
- `THRUST_SOLVER`: A CHC solver command used to solve CHC constraints generated by Thrust. Default: `z3`
122+
- `THRUST_SOLVER_ARGS`: Whitespace-separated command-line flags passed to the solver. The default is `fp.spacer.global=true fp.validate=true` when the solver is `z3`.
123+
- `THRUST_SOLVER_TIMEOUT_SECS`: Timeout for waiting on results from the solver. Default: `30`
124+
- `THRUST_OUTPUT_DIR`: When configured, Thrust outputs intermediate smtlib2 files into this directory.
125+
- `THRUST_ENUM_EXPANSION_DEPTH_LIMIT`: When Thrust works with enums, it "expands" the structure of the enum value onto its environment. This configuration value sets the limit on the depth of recursion during this expansion to handle enums that are defined recursively. It is our future work to discover a sensible value for this automatically. Default: `2`
126+
69127
## Development
70128

71129
The implementation of the Thrust is largely divided into the following modules.

0 commit comments

Comments
 (0)