Rust is the deployment backend for Aver.
Use it when you want:
- a native Cargo project
- a normal Rust build/test/run loop
- deployment without the Aver runtime
aver compile examples/core/hello.av -o /tmp/hello-rs
cd /tmp/hello-rs && cargo build && cargo runOutput:
Compiled examples/core/hello.av → /tmp/hello-rs/ [Rust]
cd /tmp/hello-rs && cargo build && cargo run
Generates a complete Cargo project:
out/
Cargo.toml
src/
main.rs
runtime_support.rs
aver_generated/
mod.rs
entry/
mod.rs
...
The generated project includes:
src/main.rswith the runtime prelude and final entrypointsrc/runtime_support.rsfor the sharedaver-rtbridge and shared runtime typessrc/replay_support.rswhen--with-replayis enabledsrc/aver_generated/.../mod.rsfiles that preserve the Aver module graph as Rust modulessrc/verify.rswhen the entry module hasverifyblocks
The generated Rust keeps:
- user-defined types as Rust
structs andenums inside their originating modules - direct
depends [...]modules as explicit Rust imports inside generated module files - module-qualified Aver calls such as
Domain.Tasks.replayTask(...)as qualified Rust paths fn main()insrc/main.rsdelegating toaver_generated::entry::main()#[cfg(test)]verify blocks as Rust tests for the entry module
src/main.rs includes:
- runtime bridge (
aver_rtmodule re-exporting the sharedaver-rtcrate) - shared runtime type imports for built-in service records when needed
- the root
aver_generatedmodule tree - the final
fn main()entry point
Generated Cargo projects now target Rust edition 2024.
Cargo.toml is generated around the shared aver-rt runtime crate. Service-specific runtime features are enabled only when needed:
| Aver service | Rust crate |
|---|---|
no Http effects |
aver-rt = { version = "=0.2.1" } |
Http effects present |
aver-rt = { version = "=0.2.1", features = ["http"] } |
ureq is pulled transitively by aver-rt/http; generated projects do not declare it directly.
For local runtime development from the Aver repository, set AVER_RUNTIME_PATH before running aver compile to force a path dependency instead of the crates.io release:
AVER_RUNTIME_PATH="$(pwd)/aver-rt" aver compile examples/core/hello.av -o /tmp/hello-rsUse --with-replay when the generated binary should understand deterministic record/replay:
aver compile self_hosted/main.av \
--module-root self_hosted \
--with-replay \
--guest-entry runGuestProgram \
-o /tmp/aver-selfThis emits src/replay_support.rs and adds the serde / serde_json / toml dependencies needed for recording files and guest-scoped runtime policy. Without --with-replay, generated projects stay smaller and do not carry replay support.
Use --with-self-host-support only for generated programs that are themselves self-host-like meta-runtimes and need SelfHostRuntime.* builtins such as the self-hosted HttpServer bridge:
aver compile self_hosted/main.av \
--module-root self_hosted \
--with-replay \
--policy runtime \
--guest-entry runGuestCliProgram \
--with-self-host-support \
-o /tmp/aver-selfThis emits a separate src/self_host_support.rs module. It is intentionally not part of the generic generated runtime.
Generated Rust also exposes policy mode explicitly:
aver compile app.av --policy embed
aver compile app.av --policy runtime--policy embedbakes the currentaver.tomlinto the generated project--policy runtimeloadsaver.tomlfrom the active module root when the binary runs- default:
embedfor plaincompile,runtimewhen--with-replayis enabled
--guest-entry matters for meta-runtimes such as the self-hosted interpreter:
- bootstrap/tooling work stays outside record/replay and policy scope
- only the chosen guest entry runs inside the scoped runtime
aver.tomlpolicy and replay interception start at that boundary- policy is loaded at runtime from the guest module root instead of being baked into the binary
For --with-self-host-support, the chosen --guest-entry has an additional explicit contract:
- it must declare
prog: Program - it must declare
moduleFns: List<FnDef>
Generated Rust uses those two parameters to install the temporary self-host callback store around the guest execution boundary. If the contract is not met, aver compile now fails early with a readable error instead of generating a broken project.
When the guest entry has a parameter named guestArgs: List<String>, generated replay support treats that parameter as the guest CLI input:
Args.get()inside the scoped guest run returnsguestArgs- replay
inputrecords onlyguestArgs, not the outer wrapper arguments - self-host bootstrap args such as
program_fileandmodule_rootstay outside the guest trace
SelfHostRuntime.* is also gated explicitly now:
- if generated code uses
SelfHostRuntime.*,aver compilerequires--with-self-host-support - this detection includes top-level statements, not only function bodies
All language features are transpilable:
| Feature | Status |
|---|---|
| Arithmetic, comparisons, string interpolation | OK |
match with all pattern types |
OK |
Result<T,E>, Option<T> constructors + match |
OK |
User-defined sum types (type Shape) |
OK |
User-defined records (record User) |
OK |
Record update (User.update(u, field = val)) |
OK |
List literals, List.* operations |
OK |
Map literals, Map.* operations |
OK |
| Tuple literals, tuple patterns | OK |
Error propagation (?) |
OK |
| Auto-memoization | OK |
| Tail-call optimization | OK |
Module imports (depends [X]) |
OK |
Console service |
OK |
Http service |
OK |
HttpServer service (listen, listenWith) |
OK |
Tcp service (persistent connections) |
OK |
Disk service |
OK |
Env service |
OK |
Random service |
OK |
Time service |
OK |
Terminal service (feature-gated) |
OK |
Args service |
OK |
verify blocks → #[cfg(test)] |
OK |
Exact method-level effects (Http.get, Disk.readText, etc.) |
OK |
Verify blocks are emitted as #[test] functions:
aver compile examples/core/calculator.av -o /tmp/calc
cd /tmp/calc && cargo testWhen a program has depends [Data.Fibonacci], the transpiler:
- loads the dependent
.avfile recursively, with circular import detection - lowers each Aver module into a Rust module under
src/aver_generated/... - imports direct
depends [...]modules explicitly in the generated Rust - keeps qualified calls module-qualified:
Data.Fibonacci.fibbecomescrate::aver_generated::data::fibonacci::fib
This avoids the old giant single-file output and keeps medium projects reviewable in generated Rust.
Generated Rust uses aver-rt as the shared runtime. The actual service implementations live there:
Tcp: sharedaver-rt::tcpruntime with persistent connection mapHttp: sharedaver-rt::httpclient, enabled by thehttpfeatureHttpServer: sharedaver-rt::http_serverloop and request/response typesConsole,Time,Disk,Env,Args: shared helpers fromaver-rt