Skip to content

fix(decoder): correct GC rec-group canonicalization — drive down type-subtyping conformance (#149)#359

Merged
avrabe merged 2 commits into
mainfrom
fix/149-gc-subtyping-callindirect-table
Jun 24, 2026
Merged

fix(decoder): correct GC rec-group canonicalization — drive down type-subtyping conformance (#149)#359
avrabe merged 2 commits into
mainfrom
fix/149-gc-subtyping-callindirect-table

Conversation

@avrabe

@avrabe avrabe commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes WebAssembly-GC reference-type subtyping conformance (issue #149). The type-subtyping.wast conformance cluster was failing because call_indirect / return_call_indirect validation rejected any table whose element type was not exactly funcref. Per the WebAssembly-GC spec the table's element type need only be a subtype of funcref, so a typed function-reference table such as (ref null $t) (where $t is a function type) is valid.

The too-strict equality check elem_type != RefType::Funcref rejected the valid (ref null $t2) table in the module at type-subtyping.wast ~line 320, which cascaded the exported run function to "not exported" (the module failed to instantiate).

Root cause (empirical)

Instrumented the validator (instrumentation removed before commit) and traced the actual failing module to func_idx=2 type_idx=0 (run, type (func)), failing on a call_indirect over a (ref null $t2) table — not a rec-group canonical-id collapse. The canonicalization/subtype walker read correct for the $t0 <: $t1 <: $t2 sub-chains; the false subtype results observed elsewhere were the correct outcomes for unrelated assert_invalid / ref.test cases. The locus was the element-type check only.

Fix

Replaced the equality check with the existing is_ref_type_subtype(elem, funcref, module) helper in both call_indirect (0x11) and return_call_indirect (0x13). Also removed two pre-existing /tmp-file debug blocks that violated the project's tracing rule.

Measured oracle (from source, not the installed binary)

type-subtyping cluster:

  • Before: 115 passed / 2 failed assertions (file failing)
  • After: 117 passed / 0 failed (file passes)

Full WAST suite (external/testsuite, legacy auto-excluded):

  • Before: 261 files passed / 19 failed; 65776 assertions passed / 531 failed
  • After: 262 files passed / 18 failed; 65778 assertions passed / 529 failed

Per-file failure diff before→after: only type-subtyping.wast changed (2 → 0). Every other file is byte-identical in failure count — zero regressions.

🤖 Generated with Claude Code

avrabe and others added 2 commits June 24, 2026 06:22
…cause (#149)

Feature-loop step 3 for the GC-subtyping conformance fix. Records the
measure-first oracle (type-subtyping.wast = 90 pass / 27 fail, failure modes
characterised) and the root-cause (rec-group type_canonical_ids canonicalization
collapsing distinct types; consumed by wast_execution import-linking +
wast_validator subtype checks). The fix gates on driving 27 down without
regressing the full suite (mandatory full-suite gate — ~400 historical
regressions when subtyping is touched naively). derives-from REQ_FUNC_022.

rivet validate: 0 errors.
…#149)

WebAssembly-GC type-subtyping conformance: the wast validator rejected
`call_indirect` / `return_call_indirect` whenever the table's element type
was not *exactly* `funcref`. Per the spec the table type need only be a
subtype of `funcref`, so a typed function-reference table such as
`(ref null $t)` (where `$t` is a function type) is valid. The equality
check `elem_type != RefType::Funcref` was too strict and rejected the
valid `(ref null $t2)` table in type-subtyping.wast, cascading the
exported `run` function to "not exported" because the module failed to
instantiate.

Empirical root-cause (instrumented, then removed): the failing module was
the call_indirect-over-typed-table case (type-subtyping.wast lines ~320),
not a rec-group canonical-id collapse — the canonicalization walker read
correct for the sub-chains. Fix is the element-type check only; replaced
the equality with the existing `is_ref_type_subtype(elem, funcref)` helper
in both call_indirect (0x11) and return_call_indirect (0x13). Also removed
two pre-existing /tmp-file debug blocks that violated the tracing rule.

Oracle (measured from source, not the installed binary):
  type-subtyping cluster: 2 failing assertions -> 0 (file now passes,
    117/117 assertions).
  Full WAST suite: 261 -> 262 files passing, 19 -> 18 failing;
    65776 -> 65778 assertions passing, 531 -> 529 failing.
  Per-file failure diff: only type-subtyping.wast changed (2 -> 0);
    every other file byte-identical. Zero regressions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Trace: AD-QUALITY-001
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

🔍 Build Diagnostics Report

Summary

Metric Base Branch This PR Change
Errors 0 0 0
Warnings 5 5 0

🎯 Impact Analysis

Issues in Files You Modified

  • 0 new errors introduced by your changes
  • 0 new warnings introduced by your changes
  • 0 total errors in modified files
  • 0 total warnings in modified files
  • 0 files you modified

Cascading Issues (Your Changes Breaking Other Files)

  • 0 new errors in unchanged files
  • 0 new warnings in unchanged files
  • 0 unchanged files now affected

Note: "Cascading issues" are errors in files you didn't modify, caused by your changes (e.g., breaking API changes, dependency issues).

✅ No Issues Detected

Perfect! Your changes don't introduce any new errors or warnings, and don't break any existing code.


📊 Full diagnostic data available in workflow artifacts

🔧 To reproduce locally:

# Install cargo-kiln
cargo install --path cargo-kiln

# Analyze your changes
cargo-kiln build --output json --filter-severity error
cargo-kiln check --output json --filter-severity warning

@avrabe avrabe merged commit 5288bde into main Jun 24, 2026
18 checks passed
@avrabe avrabe deleted the fix/149-gc-subtyping-callindirect-table branch June 24, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant