feat(validator): NonNull StackType variants for nullability tracking#234
Open
avrabe wants to merge 5 commits into
Open
feat(validator): NonNull StackType variants for nullability tracking#234avrabe wants to merge 5 commits into
avrabe wants to merge 5 commits into
Conversation
Add 8 non-nullable StackType variants (NonNullFuncRef, NonNullAnyRef, etc.) with proper subtyping: NonNullX <: X, NonNullX follows same hierarchy as X. Methods: to_non_nullable, to_nullable, is_nullable, from_value_type_with_nullability. No behavior change yet — the variants exist but aren't produced by any code path. This is the structural foundation for the nullability sidecar that will fix the remaining 15 WAST failures. Zero regressions: try_table(0), elem(0), local_init(0), i31(0). WAST: 15 failures unchanged (65,618/65,633 = 99.977%) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🔍 Build Diagnostics ReportSummary
🎯 Impact AnalysisIssues in Files You Modified
Cascading Issues (Your Changes Breaking Other Files)
✅ No Issues DetectedPerfect! 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 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Per WebAssembly/gc#516, branching instructions (br_on_null, br_on_non_null, br_on_cast, br_on_cast_fail) must validate the label type decomposition via pop_operands+push_operands, not by inspecting the current stack. The "inspect" shortcut preserves more-specific stack types across branches which masks type mismatches against the label's declared type. Fix applied: - br_on_null: pop label_types, check stack compatibility, re-push label types (normalizes types to label's declaration), then push non-null ref - br_on_non_null: validate label_last accepts non-null ref, pop/re-push the t* prefix - br_on_cast: pop rt1, then pop/re-push label_types[:-1], push diff - br_on_cast_fail: same pattern, push rt2 on fall-through Result: 15 WAST failures → 9 (99.986% conformance). Remaining 9 are in br_on_cast (1), br_on_cast_fail (1), custom-descriptors variants (4), return_call_ref (1), type-subtyping (2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a new ValueType variant `NonNullAbstract(u8)` representing a non-nullable abstract heap-type reference (e.g. `(ref any)`, `(ref func)`). The u8 is the canonical WebAssembly abstract heap-type byte. Background: the decoder currently loses non-nullability for abstract refs in function signatures — `(ref any)` and `anyref` (= `(ref null any)`) both decode to ValueType::AnyRef. This prevents the validator from enforcing non-nullability for abstract refs, blocking ~6 of the 9 remaining WAST failures (br_on_cast edge cases). This commit: - Adds `ValueType::NonNullAbstract(u8)` with Debug/to_binary/default_for_type handling - Updates exhaustive matches in 8 downstream crates to handle the new variant - Maps to `NonNullStackType::NonNull*` variants in the validator's `from_value_type` - Marks as non-defaultable in `is_defaultable` The decoder is NOT yet updated to produce this variant — doing so requires updates to ValueType equality/subtype functions that compare by variant. Enabling decoder production without those updates caused a 78-failure regression. This commit just lays the infrastructure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…es (9→4) Activates the dormant ValueType::NonNullAbstract variant by having decoders produce it for non-nullable abstract heap types. Adds supporting subtype rules and fixes catch_ref handler type per spec. Changes: Decoder (kiln-decoder/streaming_decoder.rs): - parse_value_type now returns NonNullAbstract(byte) for non-nullable abstract heap refs like (ref any), (ref func), (ref exn). - parse_value_type_for_local delegates to parse_value_type (sentinel encoding removed — NonNullAbstract supersedes it). Validator (kiln-build-core/wast_validator.rs): - parse_heap_type now returns NonNullAbstract(byte) for non-nullable abstract block types in the 0x63/0x64 encoding. - br_on_cast / br_on_cast_fail: apply to_non_nullable() on ht1/ht2/diff so the subtype check against label types correctly enforces nullability. - catch_ref / catch_all_ref: push NonNullExnRef (not ExnRef) per spec — exception references handed to catch handlers are non-null. - is_subtype_of: added hierarchy rules for NonNull abstract refs (NonNullStructRef <: NonNullEqRef <: NonNullAnyRef, etc.). - is_subtype_of_in_module: added rules for TypedFuncRef(_, false) <: NonNullFuncRef/StructRef/ArrayRef/EqRef/AnyRef based on concrete kind. Runtime foundation (kiln-foundation/values.rs): - matches_type: NonNullAbstract(byte) matches the corresponding non-null Value variant (and its subtype hierarchy: i31<:eq<:any etc). Result: 9 WAST failures → 4. 99.994% conformance. Remaining 4 are module validation rejections in br_on_cast custom-descriptors (2), type-subtyping (1), and a cascaded assert_return from the type-subtyping rejection (1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The WebAssembly GC spec permits tables of type (ref null \$t) where \$t is a function type to be used with call_indirect / return_call_indirect. Our validator previously rejected any table that wasn't exactly the abstract funcref. Now we accept any ref type whose heap type is in the func hierarchy (funcref, (ref null \$func_type), nofunc). Fixes type-subtyping.wast module which uses (table (ref null \$t2) ...) with call_indirect to invoke function subtypes polymorphically. Result: 4 WAST failures → 2. 99.997% conformance. Remaining 2 are in custom-descriptors proposal modules where top-level modules contain br_on_cast with rt2 nullable and rt1 non-null — strict spec rejects but the test file expects them to validate. Proposal-specific behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Add structural foundation for StackType nullability tracking.
8 NonNull variants added with proper subtyping rules. No behavior change
yet — the variants exist but are not produced by any code path.
Next step: add parallel nullability sidecar data populated by the decoder
to actually produce NonNull types in block/function type resolution.
WAST: 15 failures unchanged (99.977%)
🤖 Generated with Claude Code