fix(codegen/verifier): monomorphize nested generic where-helpers and thread origin-module tables into imported-generic clones - #1001
Conversation
…thread origin-module tables into imported-generic clones Two mono-pipeline fixes (grounded as one cluster): #990 - generic discovery collected mono bases from top-level declarations only, so a forall<T> where-helper under a non-generic parent was never cloned and its concrete call dangled at WAT assembly (unknown func) on a check-green program. Codegen Pass 1.5 and the verifier now build their base sets with one shared collector (collect_nested_generic_decls), so nested instantiations are emitted AND verified per-monomorphization in lockstep (pinned by a new #732 differential corpus entry). The Pass-2 where-fn sweep stops at generic templates (clone hoisting owns their subtrees) and the template-warning suppression covers nested templates. #998 - mono clones of imported generics compiled with the importer's span tables, dropping the #820 widen guards the library's verify promised Tier-3 (u64.MAX -> -1, no trap). The module harvest records each unshadowed imported generic's origin path, every clone of an imported base is tagged (main worklist, shadowed mod$ clones, the transitive chase, and hoisted where-helpers inherit it), and the mono compile loop threads imported=True plus that module's tables exactly like Pass 2.5/2.6. Local clones keep the main-file tables (pinned control). Seven-mutant battery: all killed. Grounding probes surfaced two pre-existing sibling gaps, filed as #999 (imported fn's nested generic) and #1000 (private module generic reached transitively); tracker rows ride this commit. Refs #990, #998 (Closes fire on the release PR to main) Co-Authored-By: Claude <noreply@anthropic.invalid>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
📝 WalkthroughWalkthroughThis change discovers nested generic ChangesGeneric monomorphisation and widening guards
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Verifier
participant Monomorphize
participant CodeGenerator
participant ModuleTables
Verifier->>Monomorphize: discover nested generic where-helpers
Monomorphize->>CodeGenerator: emit concrete clones and record origins
CodeGenerator->>ModuleTables: select origin module tables
ModuleTables-->>CodeGenerator: provide span and target-type tables
Possibly related issues
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 7 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (7 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## release/v0.1.4 #1001 +/- ##
==================================================
+ Coverage 93.45% 93.47% +0.01%
==================================================
Files 96 96
Lines 31734 31771 +37
Branches 456 456
==================================================
+ Hits 29658 29697 +39
+ Misses 2063 2061 -2
Partials 13 13
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@TESTING.md`:
- Around line 171-175: Update the dual-target conformance differential
description in the test_wasi_target.py row to state 127 run-level conformance
programs instead of 126, and search the entire TESTING.md file for remaining
stale 126 references related to this count so all occurrences stay consistent
with the overview total.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 88c28eca-7229-4176-8fa3-76c6dcb994ae
⛔ Files ignored due to path filters (6)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**tests/conformance/ch09_generic_where_nongeneric_parent.verais excluded by!**/*.vera
📒 Files selected for processing (19)
AGENTS.mdCHANGELOG.mdCLAUDE.mdFAQ.mdKNOWN_ISSUES.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdspec/11-compilation.mdtests/conformance/manifest.jsontests/test_generic_where_helper_990.pytests/test_monomorphize_differential.pytests/test_xmod_generic_widen_gap.pyvera/codegen/core.pyvera/codegen/modules.pyvera/codegen/monomorphize.pyvera/monomorphize.pyvera/verifier.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
… tests, honest #1002 pin, docs corrections Applies the PR #1001 review round (3 toolkit agents + adversarial panel; the panel confirmed zero findings across soundness, origin-mistag, and determinism lenses): - tests: transitive imported-generic widen (same-module and 3-module chain — silently unguarded at base) plus the shadowed-body CHASE path (kills the chase-site origin mutant the original battery missed); contract-only, nested-to-nested, and recursive nested-generic shapes; a nested_generic_contract_only differential corpus entry; an honest pin of #1002 (generic helper under a generic ancestor still dangles — pre-existing, filed from this round's probes). - docs: SKILL #999 workaround rewritten (the hoist workaround was empirically refuted — the imported parent body is never scanned); KNOWN_ISSUES #999 row broadened to the mechanism (no nesting required), #1002 rows added; collect_nested_generic_decls and _flatten_where_fns docstrings corrected (hoisting substitutes only the ancestor's type vars); TESTING.md wasi-row 126->127 (CodeRabbit) and counts reconciled (7,309). Refs #990, #998, #999, #1002 Co-Authored-By: Claude <noreply@anthropic.invalid>
Review round — 3 pr-review agents + 3-lens adversarial panelThe mechanism survived everything thrown at it: the panel confirmed zero findings across its three lenses, and the round's changes are coverage hardening, one mutant-battery hole closed, an honest docs correction, and two pre-existing bugs filed. The soundness story (panel, independently of the PR's own tests)Lying-contract matrix (lens 1): a nested generic with a false Origin-routing matrix (lens 2): local+imported generics mutually instantiated route to their own tables (both directions trap at Structure (lens 3): WAT is byte-stable across hash seeds (the new dicts introduce no iteration-order effects), same-(name,types) instantiations from body + sibling + contract dedup to one clone, uninstantiated nested templates keep their E604 warning while instantiated ones are suppressed per-name (not over-broad), warm re-registration doesn't accumulate stale instances, and nested clones are never exported. Fixed in this round
Filed from this round: #1002 (+ #999 broadened)The probes found generic helpers under a generic ancestor are never monomorphized — clone hoisting substitutes only the ancestor's type vars, leaving the descendant's own Methodology noteAll probe work ran in pinned per-commit worktrees (the #997 round's contamination lesson) — zero cross-agent interference this time. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_generic_where_helper_990.py`:
- Around line 276-307: Update
test_generic_under_generic_ancestor_still_dangles_1002 to assert that at least
one error diagnostic contains “unknown func” by checking all entries in errs,
rather than indexing errs[0]. Preserve the existing failure message and `#1002`
pin behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 21bf4313-c663-484c-8ff2-8de888e1e078
⛔ Files ignored due to path filters (2)
docs/SKILL.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**
📒 Files selected for processing (11)
FAQ.mdKNOWN_ISSUES.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdtests/test_generic_where_helper_990.pytests/test_monomorphize_differential.pytests/test_xmod_generic_widen_gap.pyvera/codegen/core.pyvera/monomorphize.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
…t (PR #1001 review) Co-Authored-By: Claude <noreply@anthropic.invalid>
Summary
Fixes the two mono-pipeline bugs the cluster grounding paired: #990 (a
forall<T>where-helper under a non-generic parent is never monomorphized — check-green, verify-green,unknown funcat compile) and #998 (mono clones of imported generics compile with the importer's span tables, silently dropping the #820@Nat→@Intwiden guards the library'svera verifypromised Tier-3 —u64.MAX→-1, no trap).#990 — nested generic discovery, codegen and verifier in lockstep by construction
Generic discovery collected mono bases from top-level
program.declarationsonly. A generic helper nested in a non-generic function'swhereblock was invisible: no clone emitted, the parent's concrete-typed call lowered to the bare unmangled name, and WAT assembly failed.Both sides now build their base set with one shared collector (
vera/monomorphize.pycollect_nested_generic_decls), used by codegen Pass 1.5 and the verifier's instance discovery — so the two sides collect the identical set and each nested instantiation is emitted and verified per-monomorphization (_verify_fn's forall dispatch already keys on the decl name; the discovery fill is all it needed). The collector stops at the first generic node in either direction: a generic helper's own subtree is carried per-clone and hoisted by the #904 path, so nothing double-emits (pinned at the WAT level). The Pass-2 where-fn sweep likewise stops at a generic template's subtree, and the template-warning suppression set now includes nested templates.#998 — clone provenance: origin-module tables for imported-generic clones
The module harvest records each unshadowed imported generic's origin path (
_imported_generic_origins); every emitted clone of an imported base is tagged (_mono_clone_origins) at all three emission sites — the main worklist, the shadowedmod$…worklist, and the shadowed-body transitive chase — and per-clone hoisted where-helpers inherit their clone's origin. The mono compile loop then threadsimported=True+ that module'smodule_artifactstable for tagged clones exactly like Pass 2.5/2.6 bodies (monomorphization preserves node spans, so the template module's table keys the clone body correctly; absent tables fall back to the #986 suppression, never a wrong-file guard). A local generic's clones carry no tag and keep the main-file tables.Evidence
tests/test_generic_where_helper_990.pyfailed with the exactunknown func $giddiagnostic (4 tests); the flippedtests/test_xmod_generic_widen_gap.pyfailed withtrap kind None(silent widen) at the unshadowed, shadowed, and hoisted-helper doors. All 15 flipped GREEN with the fix; controls (Generic forall<T> fn with a where-block helper crashes codegen (unknown func: helper not found) #904 hoisting, local-clone guard, shadowed in-range) were green throughout.nested_generic_where_helpercorpus entry in the Per-monomorphization static verification for generic functions #732 differential (tests/test_monomorphize_differential.py) was RED against the codegen-only fix (codegen emittedgidinstances the verifier never discovered) and is GREEN with the shared collector — the invariant now pins the lockstep permanently.imported=Falsemis-flag, and flatten-descends-into-generic — each REDs its specific test (the last one required a T-independent grandchild observable, added for exactly that reason).tests/conformance/ch09_generic_where_nongeneric_parent.verawith an enforced sentinel (156 programs); full suite 7,298 tests, mypy clean, 37 examples.Discovered along the way (filed, queued — no deferrals)
The grounding probes surfaced two pre-existing siblings (confirmed identical at the
75f1ff4base): #999 (a nested generic inside an imported function — discovery never seeds from module bodies) and #1000 (a private module generic reached transitively from an exported one — never harvested as a clone base). Both are loud unknown-func failures, filed with repros and fix directions; KNOWN_ISSUES + SKILL rows ride this PR.Scope honesty
module_renamesthreading on the mono path) — unchanged by this PR; clone naming/resolution attribution remains the#661latent gap (comment updated to say exactly which half Monomorphized clones of imported generic fns drop the #820 component widen guards — library verify promises Tier-3, importer runs unguarded #998 added).Docs lockstep
KNOWN_ISSUES/SKILL rows for #990/#998 deleted and #999/#1000 added; spec/11's widening paragraph now states imported-generic clones are guarded (one remaining component site: the E531 generic field, #757); CHANGELOG bullets for both fixes plus the #987 bullet's residual clause updated; TESTING.md rows and all counts reconciled (7,298 tests / 156 conformance), site assets regenerated.
Closes #990
Closes #998
Summary by CodeRabbit
Bug Fixes
wherehelpers.where-helper cloning/hoisting issues (e.g.,#990) and addressed related generic-instantiation gaps across module boundaries.@Nat→@Intto reflect only the remaining unguarded@Intfield warning.Tests
forallwherehelpers and imported generic widening/trap behaviour.Documentation
@Nat→@Intspec wording.