From e83196f89e918587d8a4439969e38dbf0746446a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lennard=20G=C3=A4her?= <l.gaeher@posteo.de> Date: Wed, 12 Feb 2025 21:16:00 +0100 Subject: [PATCH] adapt docs --- docs/SPEC_FORMAT.md | 17 +++++++++++++++-- docs/tutorial.md | 6 +++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/SPEC_FORMAT.md b/docs/SPEC_FORMAT.md index b6dfa18d..df6b0f76 100644 --- a/docs/SPEC_FORMAT.md +++ b/docs/SPEC_FORMAT.md @@ -20,12 +20,25 @@ The `params` clause specifies a universally-quantified parameter of the specific The `args` clause specifies the refinement and (optionally) a type for the single argument `x` of the function. RefinedRust infers a "default" type for the argument from Rust's type, but this can also be overridden by providing an explicit type after a `@`. For instance, the clause `#[rr::args("z" @ "int i32")]` would be equivalent to the one specified above. -In addition, for types (like structs) with invariants declared on them, the argument can be prefixed with `#raw` in order to not require the invariant on them to hold (e.g. `#[rr::args("z", #raw "-[#x]")]`). +In addition, for types (like structs) with invariants declared on them, the argument can be prefixed with `#raw` in order to not require the invariant on them to hold (e.g. `#[rr::args("z", #raw "-[x]")]`). The `requires` clause specifies the requirement that the result of the addition fits into an `i32` (see [RefinedRust propositions](#refinedrust-propositions) for details on the syntax). Finally, the `returns` clause specifies a refinement (and optionally, a type) for the return value of the function. +### Shortcut attributes +As an alternative to specifying the refinement for arguments explicitly, we can also let RefinedRust automatically introduce a parameter for them. +If the `rr::args` clause is missing, RefinedRust will automatically introduce one parameter for every argument, named after the Rust variable name, and assume that the arguments are refined accordingly. +For instance, we can equivalently specify the `add_42` as: +```rust +#[rr::requires("x + 42 ∈ i32")] +#[rr::returns("x + 42")] +fn add_42(x : i32) -> i32 { + x + 42 +} +``` +For mutable reference arguments `x`, you can use the notations `x.cur` and `x.ghost` to refer to the references current value and ghost variable, respectively. + | Keyword | Purpose | Properties | Example | |-----------|------------------------------|------------|----------------------------------| @@ -43,7 +56,7 @@ Finally, the `returns` clause specifies a refinement (and optionally, a type) fo There are further attributes that influence the proof-checking behaviour: | Keyword | Purpose | Properties | Example | |-----------|------------------------------|------------|----------------------------------| -| `verify` | Tell RefinedRust to verify this function with the default specification | none | `#[rr::verify]` | +| `verify` | Tell RefinedRust to verify this function with the default specification | none | `#[rr::verify]` | | `trust_me` | generate and type-check the specification and code, but do not generate a proof | none | `#[rr::trust_me]` | | `only_spec` | only generate and type-check the specification, but do not generate the code | none | `#[rr::only_spec]` | | `skip` | ignore annotations on this function completely | none | `#[rr::skip]` | diff --git a/docs/tutorial.md b/docs/tutorial.md index 379ac58d..dcfd4a2a 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -161,18 +161,18 @@ This is why we have marked `add` as unsafe. For `add` we take the following specification: ``` #[rr::params("x", "γ")] -#[rr::args(#raw "(#(-[#x]), γ)")] +#[rr::args(#raw "((-[x]), γ)")] #[rr::requires("(x + 1 ≤ MaxInt i32)%Z")] #[rr::observe("γ": "(-[#(x+1)%Z] : plist place_rfn _)")] ``` The first noteworthy part is the `#raw` annotation on the first argument: it asserts that we do not require the invariant on `EvenInt` to currently hold. -That is why we also use `-[#x]` for the contents of the mutable reference, which is the "raw" refinement for the struct (where `x` is the refinement of the first field) without the annotated invariant. +That is why we also use `-[x]` for the contents of the mutable reference, which is the "raw" refinement for the struct (where `x` is the refinement of the first field) without the annotated invariant. As we add 1, we require that `x + 1` fits into a `i32` integer. For `add_two`, we add the following specification: ``` #[rr::params("x", "γ")] -#[rr::args("(#x, γ)")] +#[rr::args("(x, γ)")] #[rr::requires("(x + 2 ≤ MaxInt i32)%Z")] #[rr::observe("γ": "(x+2)")] ``` -- GitLab