Verus-analyzer is a version of rust-analyzer that has been modified to provide IDE support for writing Verus code and proofs, including syntax support and various IDE features.
This software is experimental and subject to change; some features are likely broken.
At present, it works best on small, self-contained Verus projects. Anything more complex
will likely fail. You may file issues, but we do not currently have dedicated engineering
support for verus-analyzer
, so your issue may not be addressed. Pull requests with
fixes are always welcome, although it is unlikely they will be reviewed immediately.
The intended use of verus-analyzer
is as a drop-in replacement for rust-analyzer
.
1. Obtain the verus-analyzer source
$ git clone https://github.com/verus-lang/verus-analyzer.git
$ cd verus-analyzer
2. Compile the verus-analyzer binary
$ cargo xtask dist
3. Unzip and make the binary executable This step is dependent on your operating system.
$ gunzip ./dist/verus-analyzer-aarch64-apple-darwin.gz
$ chmod +x ./dist/verus-analyzer-aarch64-apple-darwin
$ gunzip dist/verus-analyzer-x86_64-unknown-linux-gnu.gz
$ chmod +x dist/verus-analyzer-x86_64-unknown-linux-gnu
Locate the generated zip file dist\verus-analyzer-x86_64-pc-windows-msvc.zip
and extract it (e.g.,
through right-click + extract all). Then you should see the file dist\verus-analyzer-x86_64-pc-windows-msvc\rust-analyzer.exe
that you are going to use as the verus-analyzer binary.
To use verus-analyzer
in your IDE (e.g., VS Code, EMACS or VIM) you need to configure your IDE to use the compiled verus-analyzer
binary instead of rust-analyzer
for *.rs
files.
TODO
TODO
You will need to install the rust-analyzer
extension
code --install-extension rust-lang.rust-analyzer
Then you can configure the rust-analyzer
extensions to use the verus-analyzer
binary that you compiled. You can do so by either
- Use a new VS Code Workspace and specify the settings, or
- Adding the settings of your existing workspace through the
.vscode/settings.json
files.
You will need to add the following settings:
{
"rust-analyzer.server.path": "FULL-PATH-TO-THE-VERUS-ANALYZER-BINARY",
"rust-analyzer.checkOnSave": false
}
Note: the path must be the absolute path to the generated binary. We disable cargo-check
by setting rust-analyzer.checkOnSave
to false.
When saving the file, you may get prompted to reload the rust-analyzer
server.
When opening a Verus project with the created workspace settings or open a folder with the .vscode/settings.json
, it will use the custom binary. Otherwise, it will keep using the original rust-analyzer
binary.
Remote - SSH If you are using VS code on a remote machine make sure to setup verus-analyzer
on the remote machine and configure the settings as mentioned above with the paths on the remote machine.
There is a requirement for the IDE functionalities to work. The requirement is that rust-analyzer
expects a standard Rust project layout and the metadata(Cargo.toml
) file.
Rust-analyzer scans the project root(lib.rs
or main.rs
) and all files that are reachable from the root. If the file you are working on is not reachable from the project root, most of the IDE functionalities like "goto definition" will not work. For example, when you have a file named foo.rs
next to main.rs
, and did not import foo.rs
in main.rs
(i.e., did not add mod foo
on top of main.rs
), the IDE functionalities will not work for foo.rs
.
We also need Cargo.toml
files as in standard Rust projects. For a small project, you could start with cargo new
, and it automatically generated the Cargo.toml
file. For a larger project, you could use workspace to manage multiple crates.
This is an experimental feature that allows you to run Verus inside VS Code by saving a file. To run Verus inside VS Code, please remove "rust-analyzer.checkOnSave": false
from the .code-workspace
file, and add "rust-analyzer.checkOnSave.overrideCommand"
. The value of "rust-analyzer.checkOnSave.overrideCommand"
should be a list that contains the Verus binary. Please use the absolute path to the Verus binary that is built by vargo
.
For example, add the following entries to your workspace settings or the .vscode/settings.json
file.
"rust-analyzer.server.path": "ABSOLUTE-PATH-TO-THE-VERUS-ANALYZER-BINARY",
"rust-analyzer.checkOnSave.overrideCommand": [
"ABSOLUTE-PATH-TO-VERUS-BINARY", // e.g., /home/verus-username/verus/source/target-verus/(debug|release)/verus
]
}
To provide extra arguments, add extra_args
at [package.metadata.verus.ide]
inside your Cargo.toml
file. For example, if you want to run Verus with --crate-type=dylib --expand-errors
, you could add the following at the bottom of your Cargo.toml
file.
[package.metadata.verus.ide]
extra_args = "--crate-type=dylib --expand-errors"
Please set only one of rust-analyzer.checkOnSave.overrideCommand
and rust-analyzer.checkOnSave
in the .code-workspace
file, depending as to whether you want to run Verus inside VS Code or not.
We extended rust-analyzer's grammar for Verus-specific syntax. This custom rust-analyzer highlights reserved Verus keywords (e.g., spec
, proof
, requires
, ensures
). If a user types prof
instead of proof
, a syntax error will be generated for it.
You can find more documents for IDE functionalities on the following links.
-
Code scanning is incomplete for Verus-specific items. To be specific, requires/ensures/decreases/invariant/assert-by-block/assert-forall-block are not fully scanned for IDE purposes (e.g., might not be able to "goto definition" of the function used in requires/ensures, "find all references" might omit occurrences inside requires/ensures).
-
Although Verus' custom operators are parsed, thye are not registered for IDE purposes. For example, type inference around such operators might not work. (e.g.,
A ==> B
is parsed asimplies(A, B)
, but the IDE might not be able to infer thatA
andB
are Boolean). -
builtin
andvstd
are not scanned. For example, the builtin types likeint
andnat
could be shown asunknown
. Auto completion forvstd
might not work.
- This is experimental software and subject to change.
- It is intended to be used only for Verus code. (For Rust code, you can use the original binary by opening the project without the
.code-workspace
file, which is just using "open folder" in VS Code) - Multiple features of rust-analyzer might be broken or missing.
- Syntax might not be updated to the latest version of Verus.
rust-analyzer: Clear flycheck diagnostics
command can be used to clear the error messages in VS CodeDeveloper: Reload Window
can be used to reload VS Code and the verus-analyzer server instead of closing and reopening VS Code- Setting
"rust-analyzer.diagnostics.disabled": ["syntax-error"]
in the workspace setting can disable the syntax error messages in VS Code. You could also addunresolved-module
to the above list to disable the error message for unresolved modules. - There is no proper support for
buildin
/vstd
. However, in your project'sCargo.toml
file, you can addvstd
independencices
ordev-dependencies
, which might make verus-analyzer scanvstd
andbuiltin
. For example,
[dependencies]
vstd = { path = "../verus/source/vstd"} # assuming verus and the project are in the same directory
Proof actions are an experimental feature to assist developers when debugging proof failures.
Compile Verus analyzer by following the steps below. These steps are similar to the basic version with the exception of the extra flag used in step 3.
- Clone the repository:
git clone https://github.com/verus-lang/verus-analyzer.git
cd verus-analyzer
- Compile the rust-analyzer binary:
cargo xtask dist --proof-action
- Unzip the generated file (e.g.,
gunzip ./dist/verus-analyzer-aarch64-apple-darwin.gz
) - Make it executable (e.g.,
chmod +x ./dist/verus-analyzer-aarch64-apple-darwin
)
- Follow the directions for 4. Running Verus in VS Code (optional)
- verusfmt
You can install
verusfmt
using:
cargo install verusfmt --locked
You can then use which verusfmt
to get the absolute path to it.
The "settings" entry in the .code-workspace
file needs some additional configuration to provide environment variables for the verus-analyzer binary. In particular, we need to define: "VERUS_BINARY_PATH", "TMPDIR", and "VERUS_FMT_BINARY_PATH".
"rust-analyzer.server.extraEnv": {
"VERUS_BINARY_PATH" : "ABSOLUTE-PATH-TO-VERUS-BINARY", // e.g., /home/verus-username/verus/source/target-verus/(debug|release)/verus
"TMPDIR": "ABSOLUTE-PATH-TO-TMP-DIR", // e.g., "/home/verus-username/.tmpdir"
"VERUS_FMT_BINARY_PATH" : "ABSOLUTE-PATH-TO-VERUS-FMT", // e.g., "/home/verus-username/.cargo/bin/verusfmt"
}
Hence, the final configuration for settings
might look like the following.
"settings": {
"rust-analyzer.server.path": "ABSOLUTE-PATH-TO-THE-VERUS-ANALYZER-BINARY",
"rust-analyzer.server.extraEnv": {
"VERUS_BINARY_PATH" : "ABSOLUTE-PATH-TO-VERUS-BINARY", // e.g., /home/verus-username/verus/source/target-verus/(debug|release)/verus
"TMPDIR": "ABSOLUTE-PATH-TO-TMP-DIR", // e.g., "/home/verus-username/.tmpdir"
"VERUS_FMT_BINARY_PATH" : "ABSOLUTE-PATH-TO-VERUS-FMT", // e.g., "/home/verus-username/.cargo/bin/verusfmt"
},
"rust-analyzer.checkOnSave.overrideCommand": [
"ABSOLUTE-PATH-TO-VERUS-BINARY", // e.g., /home/verus-username/verus/source/target-verus/(debug|release)/verus
],
}