chore(deps): bump rules_rocq_rust to e4660cc (rules_rust migration; fixes Rocq Formal Proofs CI)#141
Open
avrabe wants to merge 16 commits into
Open
chore(deps): bump rules_rocq_rust to e4660cc (rules_rust migration; fixes Rocq Formal Proofs CI)#141avrabe wants to merge 16 commits into
avrabe wants to merge 16 commits into
Conversation
Picks up pulseengine/rules_rocq_rust#34 which migrates rocq-of-rust to a hermetic rules_rust toolchain, replacing the ad-hoc cargo build in coq_of_rust/private/repository.bzl. The old build failed on the CI runner with `rust-lld: error: unable to find library -lLLVM-19-rust-1.85.0-nightly`, which has kept the Rocq Formal Proofs CI check red on main since v1.0.5 (admin-merged through it for the v1.1.0 and v1.1.1 releases). Closes the v1.1.1 carry-forward item (task #89). Trace: REQ-12
The pin bump alone (307b65f → e4660cc1b) is necessary but not sufficient: rules_rocq_rust#34 changed the rocq_of_rust extension's API. Without matching consumer-side changes the Rocq Formal Proofs CI check fails at analysis time with module extension @@rules_rocq_rust+//coq_of_rust:extensions.bzl%rocq_of_rust does not generate repository "rocq_of_rust_source", yet it is imported as "rocq_of_rust_source" in the usage at MODULE.bazel:51:29 Updates to match the new API, modelled on the canonical consumer example at examples/rust_to_rocq/MODULE.bazel in rules_rocq_rust: - Add bazel_dep(name = "rules_nixpkgs_core", version = "0.13.0"). rules_rocq_rust's nix_repo is dev_dependency=True there, so as the root module LOOM must configure nixpkgs itself. - Add the nix_repo extension call pinning nixpkgs to the same 2026-04-01 commit the upstream example uses (Rocq 9.0.1). - rocq.toolchain: add `with_rocq_of_rust_deps = True`. - use_repo(rocq, ...): drop `rocq_nixpkgs` (no longer exported by the new extension API — the root configures nixpkgs above). - rocq_of_rust.toolchain: drop the `commit = "..."` arg; the new toolchain uses a build-time pinned default (rocq-of-rust @ 877dd65). - use_repo(rocq_of_rust, ...): replace `rocq_of_rust_source` with `rocq_of_rust_build` (the new extension's output repo name). rules_rust, crate_universe, and the hermetic Rust nightly+rustc-dev toolchain are NOT dev_dependency in rules_rocq_rust@e4660cc1b's own MODULE.bazel, so they are inherited transitively and no consumer-side plumbing is needed for them. Trace: REQ-12
Follow-up to the MODULE.bazel migration in 1e731fb. The new rules_rocq_rust API renamed the build-output repo from rocq_of_rust_source to rocq_of_rust_build; the alias in proofs/rust_verified/BUILD.bazel still pointed at the old name and held up the Rocq Formal Proofs check at analysis time with ERROR: no such package '@@[unknown repo 'rocq_of_rust_source' requested from @@]//': ... referenced by '//proofs/rust_verified:rocq_of_rust_lib' The :rocq_of_rust_main target it consumes is preserved in the new repo (verified in upstream coq_of_rust/private/rocq_of_rust_build.bzl @ e4660cc1b). Trace: REQ-12
…l change The Track A roundtrip proof was passing on the v1.0.5-era pin of rules_rocq_rust (Rocq toolchain pulled by the old ad-hoc cargo build). After bumping to e4660cc1b — which pulls Rocq 9.0.1 with a stdlib where [simpl] reduces [0 + n * 1] to [n * 1] eagerly — the existing replace (0 + n * 1) with n by lia. silently no-ops (pattern absent) and the follow-up [reflexivity] then fails with Unable to unify "Some (n, rest)" with "Some (n * 1, rest)". at proofs/codec/Roundtrip.v:123. Match the post-simpl shape directly: [replace (n * 1) with n by lia]. The proof still closes with [Qed]; no Admitteds added. Trace: REQ-12
After the rules_rocq_rust toolchain bump, proofs/stack/StackSignature.v
line 214 fails with
Unable to unify "rev (rev ?M768) = ?M768" with
"p0 :: ps = rev (rev (p0 :: ps))".
Rocq 9.0's `apply` no longer silently flips orientation when the goal
direction is reversed. The local proof obligation after
`rewrite <- Hrev` is `p0 :: ps = rev (rev (p0 :: ps))`, while
`rev_involutive : rev (rev l) = l` goes the other way — insert an
explicit `symmetry`. Same proof, same Qed, no Admitteds added.
Trace: REQ-12
The new rules_rocq_rust rocq_library rule preserves subdirectory
hierarchy under the logical prefix:
proofs/semantics/WasmSemantics.v → proofs.semantics.WasmSemantics
proofs/simplify/ConstantFolding.v → proofs.simplify.ConstantFolding
The old pin (307b65f) appears to have flattened these to plain
proofs.WasmSemantics / proofs.ConstantFolding, so every dependent
file used `From proofs Require Import X.`. Under the new rules
that resolves to logical path "proofs.X" with no .vo file at that
location and fails with:
Error: Cannot find a physical path bound to logical path
WasmSemantics with prefix proofs.
Update all 17 imports across 9 .v files to point at the correct
subdirectory:
- WasmSemantics / TermSemantics → From proofs.semantics
- ConstantFolding / Identity /
Bitwise / StrengthReduction → From proofs.simplify
No proof bodies changed; only the module path qualifiers.
Trace: REQ-12
…lds rev Follow-up to 47b45f6. That commit added a `symmetry` to fix the orientation of [apply rev_involutive], but the proof still failed one tactic later at line 216 with Unable to unify "Some {| params := p0 :: ps; results := r; kind := Fixed |}" with "Some {| params := rev ys ++ [y]; results := r; kind := Fixed |}". Cause: Rocq 9.0's [simpl] above the [replace] is more eager than the v1.1.0-era pin's, and it unfolds [rev (y :: ys)] definitionally to [rev ys ++ [y]]. The old replace pattern [(rev (y :: ys))] then no longer matches anything in the post-simpl goal, the replace silently no-ops, and [destruct k; reflexivity] fails because the goal still holds [rev ys ++ [y]] where the lemma statement has [p0 :: ps]. Match the post-simpl shape directly and route the proof obligation through a [change] back to [rev (y :: ys)] (definitionally equal), then apply the same rev-involutive identity. Same Qed, no Admitteds added. Trace: REQ-12
… 238 After 3008dbb closed compose_empty_left, compose_empty_right now fails at line 238 with Error: Found no subterm matching "?M755 - 0" in the current goal. Same root cause as the previous two simpl-eagerness fixes: Rocq 9.0's [simpl] above the [rewrite] has already reduced [length (r0 :: rs) - 0] to its [length] form, so [rewrite Nat.sub_0_r] has no subterm to match. Wrap with [try] so the proof tolerates both simpl behaviours — the v1.1.0-era pin (which left the [- 0] intact) and the new pin (which eats it). No other tactics are changed; same Qed. Trace: REQ-12
Follow-up to 672a4b5. The new pin's Rocq 9.0 [simpl] keeps eating the subterms each downstream [rewrite] wanted to match — first [?M - 0], now [rev (rev ?M)]. Same pattern, same root cause: the old pin left these untouched and the proof did explicit rewrites; the new pin reduces them eagerly so the rewrites no-op-or-error. Wrap every rewrite in the [compose_empty_right] non-empty branch with [try], so the proof tolerates whichever way [simpl] settles the term. If [simpl] reduced everything, the rewrites all no-op and [destruct k; reflexivity] closes the residual goal directly; if it left some shapes intact, the rewrites still fire. Trace: REQ-12
My earlier 9042f2e change used the wrong half of the Coq import syntax: From proofs.semantics Require Import WasmSemantics. (wrong) `From X Require Import Y.` looks for module path `X.Y`, but `X` must match an existing `-Q` prefix binding. The new rules_rocq_rust `rocq_library` produces only the `proofs` prefix binding (from `ctx.label.package`), not `proofs.semantics`. So coqc reports: Cannot find a physical path bound to logical path WasmSemantics with prefix proofs.semantics. The subdir hierarchy belongs in the Import part, not the From part: From proofs Require Import semantics.WasmSemantics. (right) The `proofs` prefix matches the `-Q` binding; `semantics.WasmSemantics` is the path *within* that prefix and resolves to the .vo at `proofs/semantics/WasmSemantics.vo`. Apply to all 17 imports across the 7 dependent files. Pure text-level fix; no proof bodies touched. Trace: REQ-12
The try-wrapped rewrites from 4834176 still left compose_empty_right failing at line 246: Unable to unify "Some {| ...; results := r0 :: rs; ... |}" with "Some {| ...; results := rev (rev rs ++ [r0]); ... |}". Rocq 9.0's simpl unfolds the *inner* rev (r0 :: rs) definitionally to rev rs ++ [r0], so the results field becomes rev (rev rs ++ [r0]). [rewrite rev_involutive] cannot fire — its pattern rev (rev ?M) does not match rev (rev rs ++ [r0]) (the inner term is an append, not a rev). The try-wrap therefore no-ops and the goal stays unreduced. rev rs ++ [r0] is definitionally rev (r0 :: rs), so replace the field with r0 :: rs and discharge via change + rev_involutive. Uses only rev_involutive (known to resolve) and a definitional change — no guess at possibly-renamed stdlib lemma names (rev_app_distr / rev_unit). Trace: REQ-12
Root cause of the recurring TermSemantics.v "Cannot find a physical path bound to logical path WasmSemantics" error, found by reading the new rocq_library impl (rules_rocq_rust@e4660cc1b, rocq/private/rocq.bzl): each source's coqc action gets inputs = [src] + dep_vo_files + stdlib + ... where dep_vo_files comes ONLY from `deps` (transitive_compiled). The .vo files compiled from *sibling sources in the same library* are never added as inputs to later compilations in that library. So in the two-file :semantics target, TermSemantics.v was compiled without WasmSemantics.vo present — no import syntax could fix that. Two-part fix: 1. proofs/BUILD.bazel: split :semantics (WasmSemantics.v + TermSemantics.v) into two single-file rocq_library targets, :wasm_semantics and :term_semantics (deps = [:wasm_semantics]). The cross-file dependency now flows through `deps`, which DOES propagate the include path and wire the .vo as a compile input. Replace the :semantics alias pair + :semantics_test with the two real libraries and their _test targets (the names all_proofs_test already referenced — closing the stale test_suite warning too). 2. The dependent .v files now use plain `Require Import WasmSemantics.` (no `From proofs`). Plain Require resolves by logical-name suffix across every -Q loadpath, so it is invariant to whether the rule maps the .vo to `proofs.WasmSemantics` or `proofs.semantics.WasmSemantics` — the prefix ambiguity that caused two earlier failed attempts. All 17 imports across 7 files updated. Trace: REQ-12
…y_right The semantics library split (3640b98) cleared the import errors; the build now reaches StackSignature.v again, failing at the [replace] block I added in 277627f: Unable to unify "Some {| ...; results := r0 :: rs; ... |}" with "Some {| ...; results := (r0 :: rs) ++ []; ... |}". The [replace] correctly reduced [rev (rev rs ++ [r0])] to [r0 :: rs], but the surrounding [++ results empty_sig] = [++ []] survived (the pre-replace [try rewrite app_nil_r] fired on a different occurrence / shape). Add a [try rewrite app_nil_r] after the replace to discharge the residual append before [destruct k; reflexivity]. Trace: REQ-12
Empirical fix, modelled on the working pulseengine/meld proofs
(proofs/spec/BUILD.bazel) which solve exactly this inter-file
dependency case under the same rules_rocq_rust rule.
The meld idiom, applied here:
1. one rocq_library per .v file (already done in the prior split);
2. inter-file deps wired through `deps` (already done);
3. a SHARED explicit include_path on every library in the group
(meld uses "MeldSpec"; loom now uses "LoomProofs"); and
4. cross-file imports written `From <Prefix> Require Import <Module>`.
Why the earlier attempts failed: the rules_rocq_rust rocq_library
rule maps a library's .vo under `-Q <output_dir> <include_path>`,
where include_path defaults to the BUILD package path. loom's .v
files live in SUBDIRECTORIES of the proofs/ package, so the
package-derived prefix did not line up with where the .vo landed,
and neither plain `Require Import` nor a `From proofs[.subdir]`
guess could resolve the dependency's module. A shared explicit
include_path gives every library a stable logical prefix independent
of Bazel's per-target output-dir layout — which is precisely why meld
sets it on every spec library.
Changes:
- proofs/BUILD.bazel: include_path = "LoomProofs" on all 8 libraries
in the inter-dependent group (wasm_semantics, term_semantics, the
five simplify libs, correctness). The standalone glob libraries
(stack/codec/isle — no cross-proof deps) are unchanged.
- 17 cross-proof imports across 7 .v files rewritten to
`From LoomProofs Require Import <Module>`.
stack/codec/isle proofs are independent single-file groups with no
inter-file deps, so they keep the plain glob layout.
Trace: REQ-12
Two mechanical Rocq-9.0 fixes in proofs/codec/Roundtrip.v, both verified locally via `bazel build //proofs:codec_proofs` (now PASSES) using the nix-hermetic Rocq 9.0.1 toolchain: - functypes_roundtrip_n (was line 551): Rocq 9.0's `simpl` unfolds the `decode_functype` Definition itself, leaving no `decode_functype (_)` subterm for `rewrite functype_roundtrip`. Use `cbn [length encode_functypes decode_functypes_n]` so the structural fixpoints unfold but `decode_functype` stays folded for the rewrite. - roundtrip_identity (was line 646): `rewrite <- !app_assoc` (one-or- more) errors because 9.0's `simpl` already right-associates the section appends. Changed to `<- ?app_assoc` (zero-or-more): a no-op when simpl already normalized, still correct otherwise. Verified locally: codec_proofs, stack_proofs, isle_proofs all build. TermSemantics.v is a separate, deeper issue (see PR discussion) — not touched here. Trace: REQ-12
…141) Locally-verified foundation for fixing simplify_preserves_semantics (per the Option-A well-typedness decision). Both new pieces compile clean under the nix-hermetic Rocq 9.0 toolchain (verified: the build error remains only at the pre-existing theorem below them): - HasType : Term -> ValueType : a 42-rule static typing relation mirroring wasm. i64 comparisons produce TI32 even on TI64 operands; TDrop/TNop produce no value and so have no rule (they always TRFail). - canonical_forms : HasType t ty -> a well-typed term evaluates to a value of its type (never TRFail), by induction on the derivation. NOT yet done (theorem rework deferred — see PR discussion): the identity arms (x+0=x, …) need a SECOND invariant beyond well-typedness — a wrappedness invariant — because a TI32Const may hold an unwrapped Z, making eval(x+0)=VI32(wrap32 v) <> VI32 v. Reworking the theorem also changes its signature (adds the HasType hypothesis), which ripples into the callers in Correctness.v and Identity.v. The old theorem is left intact (still failing at its TI32Add case) rather than Admitted, because its current statement `forall t, term_equiv t (simplify t)` is FALSE and must not be admitted. stack/codec/isle proof targets remain green (committed in d609a31). Trace: REQ-12
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.
Summary
Picks up pulseengine/rules_rocq_rust#34 which migrates
rocq-of-rustto a hermeticrules_rusttoolchain, replacing the ad-hoccargo buildincoq_of_rust/private/repository.bzl.The old build was failing on the CI runner with
rust-lld: error: unable to find library -lLLVM-19-rust-1.85.0-nightly, keeping theRocq Formal ProofsCI check red on main since v1.0.5 and forcing admin-merge through it for the v1.1.0 and v1.1.1 releases.rules_rocq_rustPR #34's own CI confirms the migrated toolchain builds (Build Example (Linux)and(macOS)both pass).Closes
Test plan
Rocq Formal ProofsCI check on this PR goes green (the whole point)