Bazel rules for Verus SMT-backed Rust verification. Downloads pre-built Verus release binaries from GitHub with hermetic toolchain support.
Note
Part of the PulseEngine toolchain. Provides Verus verification infrastructure used across PulseEngine for Rust correctness proofs.
bazel_dep(name = "rules_verus", version = "0.1.0")
git_override(
module_name = "rules_verus",
remote = "https://github.com/pulseengine/rules_verus.git",
commit = "<latest-commit>",
)
# Configure Verus toolchain — automatically downloads Verus binaries
# AND the matching Rust sysroot (no host rustup or rules_rust toolchain needed)
verus = use_extension("@rules_verus//verus:extensions.bzl", "verus")
verus.toolchain(version = "0.2026.02.15")
use_repo(verus, "verus_toolchains")
register_toolchains("@verus_toolchains//:all")// counter.rs
use vstd::prelude::*;
verus! {
pub struct Counter {
pub value: u64,
}
impl Counter {
pub spec fn valid(&self) -> bool {
self.value < u64::MAX
}
pub fn increment(&mut self)
requires old(self).valid(),
ensures self.value == old(self).value + 1,
{
self.value = self.value + 1;
}
}
} // verus!load("@rules_verus//verus:defs.bzl", "verus_library", "verus_test")
verus_library(
name = "counter_verified",
srcs = ["counter.rs"],
)
verus_test(
name = "counter_test",
srcs = ["counter.rs"],
)# Verify (produces stamp file on success)
bazel build //:counter_verified
# Run as test
bazel test //:counter_testFor crates with multiple source files, list all files in srcs and optionally specify a crate_root:
verus_library(
name = "my_proofs",
srcs = [
"src/lib.rs",
"src/vec_proofs.rs",
"src/map_proofs.rs",
],
crate_root = "src/lib.rs", # Optional: defaults to lib.rs in srcs, or srcs[0]
crate_name = "my_proofs", # Optional: defaults to target name
)The crate_root file should contain mod declarations for the other source files:
// src/lib.rs
mod vec_proofs;
mod map_proofs;Use deps to express verification dependencies between crates. Downstream targets automatically wait for upstream verification to complete.
# Base verified library
verus_library(
name = "foundation_proofs",
srcs = ["foundation.rs"],
)
# Depends on foundation_proofs verification
verus_library(
name = "runtime_proofs",
srcs = ["runtime.rs"],
deps = [":foundation_proofs"],
)
# Test that depends on both
verus_test(
name = "integration_test",
srcs = ["integration.rs"],
deps = [
":foundation_proofs",
":runtime_proofs",
],
)When deps are specified, the rule passes --extern {crate_name}={stamp_path} to Verus for each dependency, enabling cross-crate verification.
Verifies Rust source files with Verus. Produces a stamp file on success.
| Attribute | Type | Description |
|---|---|---|
srcs |
label_list |
Rust source files to verify (.rs). Required. |
crate_root |
label |
Explicit crate root file. If not set, uses lib.rs from srcs or srcs[0]. |
crate_name |
string |
Crate name for --crate-name flag. Defaults to target name with hyphens as underscores. |
deps |
label_list |
Other verus_library targets this depends on for --extern resolution. |
extra_flags |
string_list |
Extra flags to pass to Verus (e.g., ["--multiple-errors", "5"]). |
Test target that runs Verus verification. Passes if all proofs verify.
| Attribute | Type | Description |
|---|---|---|
srcs |
label_list |
Rust source files to verify (.rs). Required. |
crate_root |
label |
Explicit crate root file. If not set, uses lib.rs from srcs or srcs[0]. |
crate_name |
string |
Crate name for --crate-name flag. Defaults to target name with hyphens as underscores. |
deps |
label_list |
Other verus_library targets this depends on for --extern resolution. |
extra_flags |
string_list |
Extra flags to pass to Verus. |
Strip Verus verification annotations from Rust source files, producing plain Rust suitable for cargo test, cargo kani, coq_of_rust, or any standard Rust tooling.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
srcs |
label_list |
Yes | — | Verus-annotated Rust source files (.rs) to strip |
Output: One stripped .rs file per input (same basename), with all Verus annotations removed:
verus! { }macro wrapperuse vstd::*importspub open spec fn/pub closed spec fn/pub proof fn(entire items)requires/ensures/invariant/decreases/recommendsclauses- Named return type bindings:
-> (name: Type)becomes-> Type - Verus
assert(...)proof assertions (no!) #[verifier::*]and#[trigger]attributes
Test that stripping Verus annotations from source files produces output matching expected plain Rust files.
| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
verus_srcs |
label_list |
Yes | — | Verus-annotated Rust source files |
plain_srcs |
label_list |
Yes | — | Expected plain Rust files (matched by basename) |
The verus-strip binary is also available for direct use:
# Strip to stdout
bazel run //tools/verus-strip:verus-strip -- input.rs
# Strip to file
bazel run //tools/verus-strip:verus-strip -- input.rs -o output.rs
# Check convergence between directories
bazel run //tools/verus-strip:verus-strip -- --check src/ plain/Verifying Kiln's safety-critical StaticVec bounded collection:
verus_library(
name = "kiln_static_vec_proofs",
srcs = [
"kiln-foundation/src/verus_proofs/mod.rs",
"kiln-foundation/src/verus_proofs/static_vec_proofs.rs",
],
crate_root = "kiln-foundation/src/verus_proofs/mod.rs",
crate_name = "kiln_static_vec_proofs",
)
verus_test(
name = "kiln_static_vec_verify",
srcs = [
"kiln-foundation/src/verus_proofs/mod.rs",
"kiln-foundation/src/verus_proofs/static_vec_proofs.rs",
],
crate_root = "kiln-foundation/src/verus_proofs/mod.rs",
crate_name = "kiln_static_vec_proofs",
)rules_verus supports the multi-track verification pattern where Verus-annotated source code
is stripped to plain Rust for use with other verification and testing tools:
src/sem.rs (Verus-annotated)
→ verus_library (SMT/Z3 verification)
→ verus_strip → plain/src/sem.rs (plain Rust)
→ cargo test, cargo kani, cargo miri, coq_of_rust
load("@rules_verus//verus:defs.bzl", "verus_library", "verus_strip", "verus_strip_test")
# Verify with Verus (SMT/Z3 track)
verus_library(
name = "sem",
srcs = ["src/sem.rs"],
)
# Strip annotations for other verification tracks
verus_strip(
name = "sem_plain",
srcs = ["src/sem.rs"],
)
# Ensure stripped output matches maintained plain/ directory
verus_strip_test(
name = "sem_convergence",
verus_srcs = ["src/sem.rs"],
plain_srcs = ["plain/src/sem.rs"],
)| Platform | Status |
|---|---|
| macOS x86_64 | Supported |
| macOS aarch64 | Supported |
| Linux x86_64 | Supported |
| Windows x86_64 | Supported |
- The module extension downloads pre-built Verus binaries from GitHub releases
- The toolchain provides the Verus binary, Z3 SMT solver, and vstd standard library
verus_libraryruns Verus verification and produces a stamp file on successverus_testwraps verification as a Bazel test target for CI integration- Cross-crate
depsensure verification ordering via stamp file dependencies verus_stripremoves Verus annotations to produce plain Rust for other tools
The Verus toolchain extension automatically downloads and bundles the matching Rust nightly
sysroot (librustc_driver, libstd, etc.) alongside the Verus binaries. This means:
- No host
rustuprequired — the sysroot is hermetically provisioned - No
rules_rusttoolchain registration needed — consumers don't need to know which nightly Verus was built against - Full sandbox support — all files are available as Bazel inputs
rules_rustis only needed forverus_strip(building from source viacrate_universe), and uses a low minimum version (>= 0.56.0) to avoid conflicts
Apache-2.0
Part of PulseEngine — formally verified WebAssembly toolchain for safety-critical systems