You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: update annotation documentation for the new macro-based syntax (#111)
* docs: update annotation documentation for the new macro-based syntax
Replace the legacy `#[thrust::requires]`/`ensures`/`param`/`ret`
annotation syntax in the README with the current `thrust_macros::*`
surface syntax, and document the rest of the current annotation system:
mutable-reference models (`*ma`/`!ma`/`Mut::new`), refinement types and
`sig`, trusted/callable functions, predicates, existentials, loop
invariants, method/trait annotations via `context`, higher-order `pre!`/
`post!`, and the `thrust_models` model types. Also refresh the
Development section to describe the thrust-macros expansion pipeline.
Refs #70https://claude.ai/code/session_019Z1nUnqp3EeceJMohsNTqe
* docs: trim annotation docs and restore callable description
Drop the Predicates/Existentials/Loop invariants/Methods/Higher-order/
Model types subsections for now, and restore the original nuance that
`#[thrust::callable]` is an alias for requiring and ensuring `true`.
Refs #70https://claude.ai/code/session_019Z1nUnqp3EeceJMohsNTqe
* docs: restore original trusted/callable example
trusted and callable are current plugin attributes, not legacy syntax,
so revert to the original rand() example and wording; only the
requires/ensures alias paths needed updating.
Refs #70https://claude.ai/code/session_019Z1nUnqp3EeceJMohsNTqe
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+32-12Lines changed: 32 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -68,11 +68,11 @@ Integration test examples are located under `tests/ui/` and can be executed usin
68
68
69
69
## Annotation
70
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.
71
+
Thrust can verify a wide range of programs without explicit annotations, but you can use `#[thrust_macros::requires(expr)]` and `#[thrust_macros::ensures(expr)]` to annotate the precondition and postcondition of a function, aiding in verification or specifying the intended behavior. Here, `expr` is an ordinary Rust expression that Thrust interprets as a logical formula. It supports the usual integer, boolean, and comparison operators, calls to functions declared with `#[thrust_macros::predicate]`, and the model operations described below.
72
72
73
73
```rust
74
-
#[thrust::requires(n >= 0)]
75
-
#[thrust::ensures((result * 2) == n * (n + 1))]
74
+
#[thrust_macros::requires(n >= 0)]
75
+
#[thrust_macros::ensures((result * 2) == n * (n + 1))]
76
76
fnsum(n:i32) ->i32 {
77
77
ifn==0 {
78
78
0
@@ -82,21 +82,29 @@ fn sum(n: i32) -> i32 {
82
82
}
83
83
```
84
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.
85
+
In an `ensures` expression, the special identifier `result` refers to the return value of the function. `requires` and `ensures` are independent: you can write either one on its own, and a missing one defaults to `true`.
86
+
87
+
### Mutable references
88
+
89
+
Within an annotation, a mutable reference `ma: &mut T` is modeled by its value at the time the function is called and its value when the function returns (the *prophecy* value). Use the deref operator `*ma` to denote the current value and the unary `!ma` to denote the final value. You can also construct a mutable-reference model directly with `thrust_models::model::Mut::new(current, final)`.
86
90
87
91
```rust
88
-
#[thrust::requires(true)]
89
-
#[thrust::ensures(^ma ==*ma + a)]
92
+
usethrust_models::model::Mut;
93
+
94
+
// `add` increments the referent by `a`. Equivalently, `!ma == *ma + a`.
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)]`.
101
+
### Refinement types
102
+
103
+
The conditions on `requires`/`ensures` are internally encoded as refinement types of the parameter and return types. You can also specify these refinement types directly. A refinement type is written `{ binder: type | formula }`, where `type` is a Rust type and `formula` constrains the value bound to `binder`. Use `#[thrust_macros::param(name: type)]` for a parameter and `#[thrust_macros::ret(type)]` for the return value:
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)]`.
117
+
`#[thrust_macros::sig(..)]` is a shorthand that combines the parameter and return refinements into a single function-signature-shaped annotation:
118
+
119
+
```rust
120
+
#[thrust_macros::sig(fn(x: { v:i32| v > 0 }) -> { r:i32| r >= x })]
121
+
fng(x:i32) ->i32 {
122
+
x
123
+
}
124
+
```
125
+
126
+
Refinements may be nested inside generic arguments and reference types, e.g. `Box<{ v: i64 | v > 0 }>` or `&mut { v: i32 | v >= 0 }`.
127
+
128
+
The bodies of functions marked with `#[thrust::trusted]` are not analyzed by Thrust. Additionally, `#[thrust::callable]` is an alias for `#[thrust_macros::requires(true)]` and `#[thrust_macros::ensures(true)]`.
110
129
111
130
```rust
112
131
#[thrust::trusted]
@@ -128,11 +147,12 @@ Several environment variables are used by Thrust to configure its behavior:
128
147
129
148
The implementation of the Thrust is largely divided into the following modules.
130
149
131
-
-`analyze`: MIR analysis. Further divided into the modules corresponding to the program units: `analyze::crate_`, `analyze::local_def`, and `analyze::basic_block`.
150
+
-`analyze`: MIR analysis. Further divided into the modules corresponding to the program units: `analyze::crate_`, `analyze::local_def`, and `analyze::basic_block`.`analyze::annot` and `analyze::annot_fn` translate the lowered annotation attributes into refinement types and formulas.
132
151
-`refine`: Typing environment and related implementations.
133
152
-`rty`: Refinement type primitives.
134
153
-`chc`: CHC and logic primitives, and it also implements an invocation of the underlying CHC solver.
135
-
-`annot`: Refinement type annotation parser.
154
+
155
+
The surface annotation syntax (`#[thrust_macros::requires]`, `ensures`, `param`, `ret`, `sig`, `predicate`, `invariant!`, `pre!`/`post!`, …) is implemented in the `thrust-macros` crate. These procedural macros expand into a small set of internal plugin attributes — chiefly `#[thrust::formula_fn]` companion functions (written as ordinary Rust over the `thrust_models` model types) together with `#[thrust::requires_path]`, `#[thrust::ensures_path]`, and `#[thrust::refinement_path(..)]` markers that link those companions to the function being specified. `analyze::annot_fn` then reads the type-checked HIR of each `formula_fn` to build the corresponding `chc::Formula`/`rty::Refinement`. The model types themselves are declared in `std.rs`, which Thrust injects into every crate it analyzes.
136
156
137
157
The implementation generates subtyping constraints in the form of CHCs (`chc::System`). The entry point is `analyze::crate_::Analyzer::run`, followed by `analyze::local_def::Analyzer::run` and `analyze::basic_block::Analyzer::run`, while accumulating the necessary information in `analyze::Analyzer`. Once `chc::System` is collected for the entire input, it invokes an external CHC solver via the `chc::solver` module and subsequently reports the result.
0 commit comments