Ask rustc whether the emitted Rust compiles (#198, step 2) - #403
Merged
Conversation
`plan` said the generator produced a file. That is a weak claim: an emission can be well-formed, contain every substring a unit test looks for, and still not type-check — `examples/emitcheck` exists because that happened once with 41 of 41 tests green over it. Every cell that produced Rust is now compiled. The state is a **receipt**, not a claim. Each cell is written to `<id>.rs`, the whole crate is checked in one pass, and each diagnostic is attributed back by the file rustc names. Nothing maps a cell to a fixture by hand — that mapping is what let #175's test pass without creating its own precondition. Verified to discriminate: `the_compile_check_separates_good_from_bad` feeds one compiling and one non-compiling unit through the real path and requires them separated. Compiler messages stay OUT of the committed report — they vary by toolchain, and `cargo test --all` runs on both 1.85 and stable, so a message in the file would make the report disagree with itself across jobs. Failing cells print their diagnostics on stderr. The check crate's dependencies are pinned exactly for the same reason: it has its own lockfile, so a caret range would let an upstream release move a cell with nothing in this repo having changed. **Exit: answers move.** 138 of 288 cells, in four classes: * 120 `plan` -> `rustc` — the new evidence. * 10 `plan` -> `bad rust` — emitted Rust that does not compile. See below. * 8 -> n/a — `Option<&T>` and `Vec<&T>` in a field or payload. Those fixtures were never legal Rust; the borrow rule only excused a spelling *starting* with `&`, so a borrow nested inside one was being measured against a struct that needs a lifetime parameter to exist. * no cell moved between `rejected` and `panic`. Three harness defects found by turning the compiler on, each of which had been producing a confident wrong answer: * the source crate was mounted as `mod probe` beside a generated `pub fn probe` wrapper — two different things sharing a name, so it is `flat` now; * a returned borrow has no lifetime to elide from, so `-> &Handle` is not Rust. Every borrow-returning cell had reported `plan` for a fixture that could not compile; the fixture writes `'static` now; * `impl Display for ZError` was being fed to the *model*, which correctly refuses an item kind the flat language does not have — failing 32 cells for a reason unrelated to their shape. The model now sees the four item kinds a `#[prebindgen]` surface declares, the same filter `emitcheck` applies. What the 10 findings are, all confirmed in the generator's own output rather than in fixture scaffolding: * JNI emits `Cow<'static, str>` **unqualified** into the consumer's scope, so a consumer that has not imported `Cow` cannot compile the file (3 cells); * C emits `flat::Option<Handle>` — a std type qualified into the source module; * C moves out of a value behind a raw pointer for `Option<data struct>` and `Option<sum>` parameters; * C calls the source function with one argument too many for a `&[T]` return, and builds a `map`/`collect` over a `Vec<&T>` return whose closure is a function item of the wrong signature; * JNI mismatches types for a `&mut T` parameter and for `&mut MaybeUninit<T>`. Part of #198, tracked by #399.
Splits the receipts step in two: rustc accepts the emitted Rust (done), and the rest of the toolchain plus the runtime states (not started).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 2 of #198 (in part), on the
shape-coveragebranch (#402).Why
plansaid the generator produced a file. That is a weaker claim than it looks: an emission can be well-formed, contain every substring a unit test looks for, and still not type-check —examples/emitcheckexists because that happened once with 41 of 41 tests green over it.Every cell that produces Rust is now handed to rustc.
The state is a receipt, not a claim
Each cell is written to
<id>.rs, the whole crate is checked in one pass, and each diagnostic is attributed back by the file rustc names. Nothing maps a cell to a fixture by hand — that mapping is exactly what let #175's regression test pass without ever creating the precondition it claimed to test.Verified to discriminate, like the coverage gate in #400:
the_compile_check_separates_good_from_badputs one compiling and one non-compiling unit through the real path and requires them separated, with the failure attributed.Two deliberate omissions from the committed report:
cargo test --allruns on both 1.85 and stable, so a message in the file would make the report disagree with itself between jobs. Failing cells print diagnostics on stderr.jni/tracing/konstare pinned exactly. Otherwise an upstream release could move a cell with nothing in this repo having changed.Exit: answers move
138 of 288 cells, in four classes and no others:
plan→rustcplan→bad rust—Option<&T>/Vec<&T>in a field or payloadrejected↔panicThe 8 that became n/a were never legal Rust: the borrow rule only excused a spelling starting with
&, so a borrow nested inside one was being measured against a struct that needs a lifetime parameter in order to exist.Three harness defects, each of which had been producing a confident wrong answer
Turning the compiler on was mostly an audit of my own fixtures:
mod probe, beside a generatedpub fn probewrapper. Two different things sharing a name; the module isflatnow.-> &Handleis not Rust at all. Every borrow-returning cell had reportedplanfor a fixture that could not have compiled. The fixture writes'staticnow, which keeps the shape and adds no parameter.impl Display for ZErrorwas being fed to the model, which correctly refuses an item kind the flat language does not have — failing 32 cells for a reason that had nothing to do with their shape. The model now sees the four item kinds a#[prebindgen]surface declares, the same filteremitcheckapplies to its own source file.Worth stating plainly: without the compiler, the first two were invisible and the third looked like a legitimate result.
What the 10 findings are
All confirmed in the generator's own output, not in fixture scaffolding (line numbers past the fixture module, checked by hand):
Kotlin/JNI
Cow<'static, str>unqualified into the consumer's scope — a consumer that has not importedCowcannot compile the file (3 cells: param, field, payload);&mut Tparameter, and for&mut MaybeUninit<T>.C
flat::Option<Handle>— a std type qualified into the source module;Option<data struct>andOption<sum>parameters;&[T]return;map/collectover aVec<&T>return whose closure is a function item of the wrong signature.I have not filed these as individual issues yet — they are cells in a committed report now, which is the point, and several look like they share a cause worth diagnosing together.
Cost
~11s added to a run, cached between runs; the check crate lives under
target/and is cleaned bycargo clean. It uses its own target directory so a nested cargo never queues behind the parent's lock.Checks
cargo test -p shape-matrix(9 tests),cargo clippy --all-targets --all-features -- -D warnings,cargo fmt --checkwith CI's config,RUSTDOCFLAGS=-D warnings cargo doc, andexamples/regen-check.shclean with every other committed artifact byte-identical.