Skip to content

Fetch a candidate's MIR with the provider that serves its body kind - #4848

Merged
feliperodri merged 2 commits into
model-checking:mainfrom
feliperodri:fix-4839-comptime-intrinsic-mir
Sep 30, 2026
Merged

feliperodri merged 2 commits into
model-checking:mainfrom
feliperodri:fix-4839-comptime-intrinsic-mir

Conversation

@feliperodri

Copy link
Copy Markdown
Member

kani autoharness aborts on any crate that declares a #[rustc_comptime] function. core has 27 of them, so the standard library run dies during candidate collection — which is what currently blocks the four autoharness jobs on model-checking/verify-rust-std#687, the same four that #4820 unblocked from the E0080 side:

do not use `optimized_mir` for constants: Const { allow_const_fn_promotion: false }

My fault, from #4820: the const-block precondition search guards its MIR fetch with is_mir_available and then calls optimized_mir. That guard is not enough — a #[rustc_comptime] function's body is a const context, which rustc's optimized_mir provider refuses to serve even while the MIR is available. instance_mir is rustc's own dispatcher between optimized_mir and mir_for_ctfe, so the fix is to stop making that choice here and use it.

The part I actually had to check: whether switching providers loses the detection #4820 exists for. It does not, and the test pins it. A #[rustc_comptime] function whose body carries const { assert!(N >= 4) } is still reported as skipped for that reason, read out of the CTFE body — and so is the plain const fn shape core::escape uses, which goes through optimized_mir as before. If someone later "simplifies" this back, that assertion is what fails.

Verified rather than read:

  • The issue's reproducer fails on main with the ICE and completes on this branch, reporting size_of::<i32> as skipped for having no body — the output the issue predicted with the panic suppressed.
  • All three shapes core has are covered and all three ICE on main: the body-less #[rustc_intrinsic] #[rustc_comptime] declaration (intrinsics::size_of), one with a body (TypeId::trait_info_of), and one with a const-block precondition. The middle one is now harnessed rather than skipped, so the CTFE body is genuinely being read.
  • script-based-pre 76/76 with the new test, kani 610/610, expected 478/478, fmt and clippy clean.

One thing for a reviewer to weigh: current_fn.rs:408 has the same is_mir_available + optimized_mir pattern, for a closure's parent. I could not construct a case that reaches it with a const-context parent, so I left it alone rather than change code I cannot test — but it is the same shape, and worth a look by someone who knows that path better.

Resolves #4839

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

`kani autoharness` aborted on any crate declaring a `#[rustc_comptime]`
function -- `core` has 27 of them, so the whole standard library run died
during candidate collection:

    do not use `optimized_mir` for constants: Const { allow_const_fn_promotion: false }

The const-block precondition search added in model-checking#4820 guarded its fetch with
`is_mir_available` and then called `optimized_mir`. That guard is not enough: a
`#[rustc_comptime]` function's body is a const context, which rustc's
`optimized_mir` provider refuses to serve even though the MIR is available.
`instance_mir` is rustc's own dispatcher between `optimized_mir` and
`mir_for_ctfe`, so use it rather than duplicating the choice here.

The three shapes `core` has are now covered by a test: a body-less
`#[rustc_intrinsic] #[rustc_comptime]` declaration (`intrinsics::size_of`), a
`#[rustc_comptime]` function with a body (`TypeId::trait_info_of`), and one
whose body carries a const-block precondition on a const generic. The last
matters most: switching providers must not lose the detection model-checking#4820 exists for,
and the test also pins the plain `const fn` shape that `core::escape` uses.

Resolves model-checking#4839
@feliperodri feliperodri self-assigned this Sep 30, 2026
rustc only lets const items, statics and const blocks call a comptime function
(`enforce_context_effects` rejects every other call), so a synthesized harness
that calls one is not a program rustc accepts. `with_body` was harnessed anyway,
and a full run reported `VERIFICATION:- FAILED` for a function that has no
runtime callers by construction.

Skip them with a new `AutoHarnessSkipReason::Comptime` ("Can only be called at
compile time"), detected the way rustc does, `tcx.constness(..)` being
`Const { always: true }`. The check runs before a generic function is
instantiated, not in `skip_reason`: `skip_reason` only sees instantiated
functions, so a generic comptime function like `guarded` would otherwise keep
its "Generic Function" reason and still go through the const-block precondition
search that model-checking#4839 was about.

`guarded_const_fn` keeps the const-block search covered, and the `instance_mir`
dispatch stays, as a backstop rather than what keeps `core` compiling.

Suggested by @tautschnig in review.
@feliperodri
feliperodri added this pull request to the merge queue Sep 30, 2026
Merged via the queue into model-checking:main with commit ce4f94c Sep 30, 2026
32 of 34 checks passed
@feliperodri
feliperodri deleted the fix-4839-comptime-intrinsic-mir branch September 30, 2026 04:00
srivatsansamraj pushed a commit to srivatsansamraj/kani that referenced this pull request Sep 30, 2026
…del-checking#4923)

Pass `--harness-timeout 5m` to
`script-based-pre/cargo_autoharness_fmt_impls`, as the other autoharness
tests (`bounded`, `bounds`, `byte_str`, `c_str`, `formatter`, `wtf8`)
already do.

**Why.** On the macOS x86_64 runners (`regression (macos-15-intel)`),
the `LowerExp`, `UpperExp` and `Pointer` harnesses of this test take
40–60 s, right at `kani autoharness`'s default `--harness-timeout` of 60
s. When one of them times out, CBMC reports `CBMC timed out` instead of
the expected failure, the test's `Failed Checks: "lower exp"` / `"upper
exp"` / `"pointer"` line is missing, and the test fails. The same
harnesses take about 10 s on Linux.

**Evidence.** I went through the logs of the `regression
(macos-15-intel)` jobs between 2026-09-28 and 2026-09-30. 33 of them
failed. This test failed in all 33, with 1–3 of those three harnesses
timing out each time, and in 32 of them it was the only failing test.
The one exception, model-checking#4903's merge-queue push run, also had
`cargo_autoharness_wtf8`'s `len` harness time out, at 5 m. On main
pushes alone, the job failed 7 times out of 12 on 2026-09-30. The
failures are independent of the changes under test:

- Today's automated toolchain upgrade, model-checking#4917: [run
36663872235](https://github.com/model-checking/kani/actions/runs/36663872235/job/109726991201)
(`LowExp`, `UpExp`, `Ptr` timed out; every other regression job passed)
- `main` pushes:
[36654469481](https://github.com/model-checking/kani/actions/runs/36654469481/job/109695682794),
[36656240395](https://github.com/model-checking/kani/actions/runs/36656240395/job/109701095388),
[36657849257](https://github.com/model-checking/kani/actions/runs/36657849257/job/109705923680),
[36659060566](https://github.com/model-checking/kani/actions/runs/36659060566/job/109709545862),
[36670355214](https://github.com/model-checking/kani/actions/runs/36670355214/job/109743820142),
[36674524840](https://github.com/model-checking/kani/actions/runs/36674524840/job/109756493668)
- Merge queue: model-checking#4895
[36650793954](https://github.com/model-checking/kani/actions/runs/36650793954/job/109684194253),
model-checking#4896
[36650908721](https://github.com/model-checking/kani/actions/runs/36650908721/job/109684568489),
model-checking#4809
[36654883143](https://github.com/model-checking/kani/actions/runs/36654883143/job/109696960300),
model-checking#4848
[36663305755](https://github.com/model-checking/kani/actions/runs/36663305755/job/109722546228),
model-checking#4903
[36667236036](https://github.com/model-checking/kani/actions/runs/36667236036/job/109734401431),
model-checking#4856
[36670723600](https://github.com/model-checking/kani/actions/runs/36670723600/job/109744937944),
model-checking#4881
[36596324505](https://github.com/model-checking/kani/actions/runs/36596324505/job/109502054372),
model-checking#4882
[36612997613](https://github.com/model-checking/kani/actions/runs/36612997613/job/109558873539)
- Pull requests: model-checking#4875
[36427316996](https://github.com/model-checking/kani/actions/runs/36427316996/job/109072277288),
model-checking#4895
[36443349794](https://github.com/model-checking/kani/actions/runs/36443349794/job/108999214513),
model-checking#4771
[36620184925](https://github.com/model-checking/kani/actions/runs/36620184925/job/109677883533)

The runner image version (`20260819.586`) was the same in passing and
failing runs.

**Manual testing.** Locally the three harnesses take about 10 s each.
Running the test with `--harness-timeout 3s` reproduces the CI failure
exactly: the same three harnesses time out, their `Failed Checks` lines
are missing, and the summary still reports 9 failures. With this change,
`cargo run -p compiletest -- --suite script-based-pre --mode exec
cargo_autoharness_fmt_impls` passes.

If the macOS Intel runner gets much slower, a longer timeout alone may
not be enough; making these three harnesses cheaper would be the next
step.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
feliperodri pushed a commit to model-checking/verify-rust-std that referenced this pull request Oct 3, 2026
On this sync, "Verify contracts with goto-transcoder" stops at `ls:
cannot access
'kani/contracts/kani_verify_std/target/x86_64-unknown-linux-gnu/debug/deps'`
([run
35923786684](https://github.com/model-checking/verify-rust-std/actions/runs/35923786684)).
Since cargo 1.99, each package's outputs go to its own
`debug/build/<package>/<hash>/out/` and `debug/deps` is no longer
created (Kani adapted to the same change in model-checking/kani#4766).
`run-kani.sh --run autoharness-analyzer` reads Kani's metadata from
`debug/deps` too; on this sync that job currently stops earlier, on the
crash fixed by model-checking/kani#4848.

Both scripts still use `debug/deps` when it exists, so nothing changes
with `main`'s toolchain. Otherwise `run-goto-transcoder.sh` takes the
`out/` directory holding the contracts that match its pattern, and the
analyzer mode links every `*.kani-metadata.json` into one temporary
directory.

Tested locally as CI runs each job:
- goto-transcoder, on this branch: without the change `ls` fails as in
CI; with it the contracts are found and goto-transcoder converts the
first, `checked_unchecked_mul_i8`. ESBMC 7.10 then segfaults on it,
which is a separate problem: the same steps with `main`'s toolchain and
Kani verify all 4 contracts.
- autoharness-analyzer, on a local update of the library to
nightly-2026-09-23 with a Kani that compiles `core` (`main` plus
model-checking/kani#4818 and model-checking/kani#4922): the metadata of
all 22 crates is found and every per-crate table is written. Their
harness counts read 0 for a separate reason, model-checking/kani#4868
(the scanner's function names now carry the crate prefix).

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.

Co-authored-by: Srivatsan Samraj <321934658+srivatsansamraj@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Z-CompilerBenchCI Tag a PR to run benchmark CI Z-EndToEndBenchCI Tag a PR to run benchmark CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Autoharness ICEs on #[rustc_comptime] intrinsics: optimized_mir called on a const-context def

2 participants