@@ -941,17 +941,32 @@ anvil-mutants-diff: anvil-mutants-diff-validate-prereqs
941941anvil-miri : anvil-miri-validate-prereqs
942942 $ErrorActionPreference = ' Stop'
943943 if ($env :ANVIL_INCLUDE_AFFECTED -eq ' --skip' ) { exit 0 }
944- # `--no-tests=pass`: miri-only exception. Tests that touch the
945- # filesystem, spawn subprocesses, or use other miri-incompatible
946- # APIs commonly carry `#[cfg_attr(miri, ignore)]` (this is the
947- # canonical opt-out for build-tooling / CLI crates). A crate
948- # whose test set ends up entirely-skipped under miri legitimately
949- # produces zero runnable tests; nextest's default exit-4 ("no
950- # tests to run") would fail the recipe in that case. We treat
951- # empty test runs as success for miri only. Other nextest-using
952- # recipes (llvm-cov) keep exit-4 as a failure because zero tests
953- # there almost always indicates a config mistake.
954- & cargo ' +{{ rust_nightly }} ' miri nextest run --no-tests=pass @(if ($env :ANVIL_INCLUDE_AFFECTED) { -split $env :ANVIL_INCLUDE_AFFECTED } else { ' --workspace' })
944+ # Run miri via libtest (`cargo miri test`), NOT `cargo miri nextest
945+ # run`. nextest uses a process-per-test model; under miri every
946+ # process pays the full cost of re-interpreting std initialization,
947+ # so process-per-test roughly DOUBLES miri wall-time on a large suite
948+ # (the dominant cost on the PR critical path). libtest runs all tests
949+ # of a binary in a single process, matching how upstream runs miri.
950+ #
951+ # `--tests` selects the same target set nextest ran -- lib unit tests,
952+ # bin unit tests, and integration tests -- while excluding doctests
953+ # (miri cannot run them) and benches/examples. We use `--tests` rather
954+ # than `--lib --tests` because `--lib` errors with "no library targets
955+ # found" on a bin-only affected package under impact scoping; `--tests`
956+ # already covers lib unit tests and tolerates libless packages. We do
957+ # NOT use `--all-targets`: it would add `--benches` (criterion benches
958+ # have `harness = false` and run a full measurement loop -- ruinously
959+ # slow under miri) and `--examples` (runs each example's `main`, often
960+ # miri-incompatible I/O), without adding doctest coverage.
961+ #
962+ # `--all-features` exercises feature-gated code so UB hidden behind an
963+ # optional feature is caught, matching how upstream runs miri.
964+ #
965+ # libtest exits 0 when a binary has zero runnable tests (e.g. a crate
966+ # whose tests are all `#[cfg_attr(miri, ignore)]` -- the canonical
967+ # opt-out for build-tooling / CLI crates), so the old nextest
968+ # `--no-tests=pass` workaround is no longer needed.
969+ & cargo ' +{{ rust_nightly }} ' miri test --all-features --tests @(if ($env :ANVIL_INCLUDE_AFFECTED) { -split $env :ANVIL_INCLUDE_AFFECTED } else { ' --workspace' })
955970 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
956971
957972# Stricter miri profiles. Each runs miri over the full workspace
@@ -973,7 +988,7 @@ anvil-miri-tree-borrows: anvil-miri-tree-borrows-validate-prereqs
973988 $pkg = @(if ($env :ANVIL_INCLUDE_AFFECTED) { -split $env :ANVIL_INCLUDE_AFFECTED } else { ' --workspace' })
974989 $env :MIRIFLAGS = " -Zmiri-tree-borrows $($env:MIRIFLAGS)" .Trim()
975990 $env :RUSTFLAGS = " --cfg miri_tree_borrows $($env:RUSTFLAGS)" .Trim()
976- & cargo ' +{{ rust_nightly }} ' miri nextest run --no- tests=pass @pkg
991+ & cargo ' +{{ rust_nightly }} ' miri test --all-features -- tests @pkg
977992 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
978993
979994[script (" pwsh" )]
@@ -983,7 +998,7 @@ anvil-miri-strict-provenance: anvil-miri-strict-provenance-validate-prereqs
983998 $pkg = @(if ($env :ANVIL_INCLUDE_AFFECTED) { -split $env :ANVIL_INCLUDE_AFFECTED } else { ' --workspace' })
984999 $env :MIRIFLAGS = " -Zmiri-strict-provenance $($env:MIRIFLAGS)" .Trim()
9851000 $env :RUSTFLAGS = " --cfg miri_strict_provenance $($env:RUSTFLAGS)" .Trim()
986- & cargo ' +{{ rust_nightly }} ' miri nextest run --no- tests=pass @pkg
1001+ & cargo ' +{{ rust_nightly }} ' miri test --all-features -- tests @pkg
9871002 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
9881003
9891004# Race coverage rotates the miri-many-seeds window daily by
@@ -1003,14 +1018,57 @@ anvil-miri-race-coverage: anvil-miri-race-coverage-validate-prereqs
10031018 $env :MIRIFLAGS = " -Zmiri-many-seeds=$low..$high $($env:MIRIFLAGS)" .Trim()
10041019 $env :RUSTFLAGS = " --cfg miri_race_coverage $($env:RUSTFLAGS)" .Trim()
10051020 Write-Host " anvil-miri-race-coverage: seed window $low..$high (day $day)"
1006- & cargo ' +{{ rust_nightly }} ' miri nextest run --no- tests=pass @pkg
1021+ & cargo ' +{{ rust_nightly }} ' miri test --all-features -- tests @pkg
10071022 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
10081023
10091024[script (" pwsh" )]
10101025anvil-careful : anvil-careful-validate-prereqs
10111026 $ErrorActionPreference = ' Stop'
10121027 if ($env :ANVIL_INCLUDE_AFFECTED -eq ' --skip' ) { exit 0 }
1013- & cargo ' +{{ rust_nightly }} ' careful test @(if ($env :ANVIL_INCLUDE_AFFECTED) { -split $env :ANVIL_INCLUDE_AFFECTED } else { ' --workspace' }) --all-features --locked
1028+ $pkg = @(if ($env :ANVIL_INCLUDE_AFFECTED) { -split $env :ANVIL_INCLUDE_AFFECTED } else { ' --workspace' })
1029+ # Guard against cargo-careful's stale-sysroot hazard. cargo-careful
1030+ # builds a custom std ("careful sysroot": debug-assertions + extra UB
1031+ # checks) into a STABLE cache path -- ProjectDirs(de.ralfj.cargo-careful),
1032+ # NOT keyed by rustc version -- and runs the workspace build with
1033+ # `--sysroot <that stable path>`. cargo's fingerprint hashes the
1034+ # RUSTFLAGS string (the stable sysroot *path*) but not the sysroot's
1035+ # *contents*. So when the pinned nightly (or the careful tool, which sets
1036+ # the std-build flags) changes, cargo-careful rebuilds that std in place
1037+ # while cargo still considers the workspace artifacts up to date -- they
1038+ # then link against a now-replaced std and fail with metadata /
1039+ # "found crate compiled by an incompatible version of rustc" errors.
1040+ #
1041+ # cargo can't see this, so we track the careful build identity ourselves
1042+ # (the nightly rustc -- commit hash et al. -- plus the careful tool
1043+ # version) and `cargo clean` when it changes, forcing the workspace to be
1044+ # rebuilt against the freshly-built std. The marker lives under target/,
1045+ # so it is wiped by the clean and travels with any target/ cache.
1046+ $rustcVV = (& rustc ' +{{ rust_nightly }} ' -vV | Out-String)
1047+ if ($LASTEXITCODE -ne 0) { Write-Error ' anvil-careful: could not query nightly rustc version' ; exit 1 }
1048+ $idSource = $rustcVV.Trim() + " `ncargo-careful {{ cargo_careful_version }} "
1049+ $sha = [System.Security.Cryptography.SHA256 ]::Create()
1050+ $idHash = ([System.BitConverter]::ToString($sha.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($idSource)))).Replace(' -' , ' ' ).ToLower()
1051+ # Human-readable identity for log output: the first `rustc -vV` line
1052+ # (e.g. "rustc 1.98.0-nightly (<hash> <date>)") plus the careful version.
1053+ $idLabel = " $(($rustcVV -split " `n" )[0].Trim()) + cargo-careful {{ cargo_careful_version }} "
1054+ $marker = Join-Path ' target' ' anvil/careful-sysroot.id'
1055+ $prev = if (Test-Path -LiteralPath $marker) { (Get-Content -LiteralPath $marker -Raw).Trim() } else { $null }
1056+ if ($null -ne $prev -and $prev -ne $idHash) {
1057+ Write-Host ' anvil-careful: careful sysroot identity changed since the last run -- running `cargo clean` so the'
1058+ Write-Host ' workspace is rebuilt against the freshly-built careful std (cargo cannot detect the in-place'
1059+ Write-Host ' sysroot rebuild on its own, so stale artifacts would otherwise fail with an'
1060+ Write-Host ' "incompatible version of rustc" / metadata mismatch).'
1061+ Write-Host " reason : the pinned nightly toolchain and/or the cargo-careful version changed"
1062+ Write-Host " now : $idLabel"
1063+ Write-Host " identity: $($prev.Substring(0, [Math]::Min(12, $prev.Length)))... -> $($idHash.Substring(0, 12))..."
1064+ cargo clean
1065+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
1066+ }
1067+ # Persist the current identity (also seeds the marker on first run, when
1068+ # there is nothing to clean). Written after the clean so it survives it.
1069+ New-Item -ItemType Directory -Force -Path (Split-Path $marker) | Out-Null
1070+ Set-Content -LiteralPath $marker -Value $idHash
1071+ & cargo ' +{{ rust_nightly }} ' careful test @pkg --all-features --locked
10141072 if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
10151073
10161074# Affected tier. `loom` is a permutation-based concurrency model
@@ -1343,32 +1401,32 @@ anvil-examples-validate-prereqs: anvil-tool-rustc-validate-prereqs
13431401# --- pr-runtime-analysis members ---
13441402
13451403[group (" anvil-setup" )]
1346- anvil-miri-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install ( anvil-tool-cargo-nextest-install installer)
1404+ anvil-miri-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install
13471405
13481406[group (" anvil-setup" )]
1349- anvil-miri-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs anvil-tool-cargo-nextest-validate-prereqs
1407+ anvil-miri-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs
13501408
13511409# The three nightly-miri profiles share the same toolchain prereqs
13521410# as anvil-miri; they only differ in the MIRIFLAGS / RUSTFLAGS the
13531411# recipe sets. Separate setup recipes keep the per-check fan-out
13541412# regular (groups.just can iterate without special-casing).
13551413[group (" anvil-setup" )]
1356- anvil-miri-tree-borrows-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install ( anvil-tool-cargo-nextest-install installer)
1414+ anvil-miri-tree-borrows-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install
13571415
13581416[group (" anvil-setup" )]
1359- anvil-miri-tree-borrows-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs anvil-tool-cargo-nextest-validate-prereqs
1417+ anvil-miri-tree-borrows-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs
13601418
13611419[group (" anvil-setup" )]
1362- anvil-miri-strict-provenance-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install ( anvil-tool-cargo-nextest-install installer)
1420+ anvil-miri-strict-provenance-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install
13631421
13641422[group (" anvil-setup" )]
1365- anvil-miri-strict-provenance-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs anvil-tool-cargo-nextest-validate-prereqs
1423+ anvil-miri-strict-provenance-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs
13661424
13671425[group (" anvil-setup" )]
1368- anvil-miri-race-coverage-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install ( anvil-tool-cargo-nextest-install installer)
1426+ anvil-miri-race-coverage-setup installer = " install": anvil-component-nightly-miri-install anvil-component-nightly-rust-src-install
13691427
13701428[group (" anvil-setup" )]
1371- anvil-miri-race-coverage-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs anvil-tool-cargo-nextest-validate-prereqs
1429+ anvil-miri-race-coverage-validate-prereqs : anvil-component-nightly-miri-validate-prereqs anvil-component-nightly-rust-src-validate-prereqs
13721430
13731431[group (" anvil-setup" )]
13741432anvil-careful-setup installer = " install": anvil-component-nightly-rust-src-install (anvil-tool-cargo-careful-install installer)
0 commit comments