Skip to main content

xtask/
miri.rs

1//! `cargo xtask miri`: the ECS's tests under Miri, which is what checks the
2//! `unsafe` in its storage.
3
4use crate::step;
5
6/// Run the ECS's tests, unit and integration and doctests alike, under Miri.
7///
8/// The world keeps its component values in `UnsafeCell`s and hands out plain
9/// references to them through `&World`, so the aliasing rules the compiler
10/// would otherwise enforce are the borrow ledger's to keep at runtime. A
11/// mistake there is undefined behaviour rather than a panic, and no test can
12/// see it: the release build reads the same bytes as the debug one. Miri is the
13/// interpreter that does check it, so this is the gate for that code, and
14/// `cargo xtask test` cannot stand in for it.
15///
16/// Miri runs the suite its own way: every test is interpreted, which is one to
17/// two orders of magnitude slower, so it names the one crate whose storage is
18/// unsafe instead of the workspace. `--all-features` is deliberate — the
19/// optional `mcp` module reads components through the same queries, so it
20/// belongs in the pass that audits them.
21///
22/// The toolchain is nightly's: Miri is not stable, and its sysroot is built
23/// against the nightly it ships with. `rustup component add miri --toolchain
24/// nightly` is what installs it; a missing one is reported as the step failing,
25/// with Miri's own message naming the component.
26pub fn run(_task: &crate::MiriArgs) -> Result<(), String> {
27    let mut command = std::process::Command::new("cargo");
28    command.args([
29        "+nightly",
30        "miri",
31        "test",
32        "-p",
33        "unlit_ecs",
34        "--all-features",
35        "--no-fail-fast",
36    ]);
37    step::run(&mut command, "miri")
38}