fix(wgsl): 8 WGSL validation fixes — Rust naga parity (#66)#68
Merged
Conversation
16 places changed from p.match(TokenSemicolon) to p.expectSemicolon(). For-loop init/update use inForHeader flag to skip (separator, not terminator). Declarations (const, var, let, override, alias, const_assert) and statements (return, break, continue, discard, assign, expr) all require ;.
WGSL spec only allows xyzw and rgba swizzle components. GLSL-only s/t/p/q components were incorrectly accepted. Additionally, mixing namespaces (e.g., v.xg combining xyzw with rgba) was not rejected. Matches Rust naga Components::new() which validates all characters belong to the same namespace (xyzw or rgba). BUG-WGSL-004: reject stpq swizzle BUG-WGSL-008: reject mixed swizzle namespace
@compute entry points without @workgroup_size were silently accepted, defaulting to [1,1,1]. WGSL spec requires @workgroup_size to be explicitly present on compute shader entry points. Matches Rust naga: Error::MissingWorkgroupSize. BUG-WGSL-003
array<f32, 0> was silently accepted. WGSL spec requires array size to be a positive integer. Now returns a clear error message. BUG-WGSL-007
Previously const_assert was parsed but treated as a no-op during lowering. Now const_assert expressions are evaluated at both module and function scope, matching Rust naga's ConstAssertFailed / NotBool behavior. Supports bool literals, negation (!), logical operators (&&, ||), comparison operators (==, !=, <, <=, >, >=), and named constants.
Functions marked with @must_use now produce an error when their return value is discarded as a statement (e.g. foo();). The result must be used in an assignment, return, expression, or phony (_ =). Matches Rust naga's FunctionMustUseUnused validation.
Complex const_assert expressions (select(), all(), float comparisons) are silently accepted when they cannot be evaluated by the simple constant evaluator. This prevents regressions on valid shaders like const_assert.wgsl and select.wgsl while still catching the common case of const_assert false.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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
WGSL validation hardening — 8 spec-compliance fixes, all verified against Rust naga.
Fixes
@must_useenforcement — reject discarded results from must-use functions@computerequires@workgroup_size— missing attribute now errorsconst_assertevaluation —const_assert falsenow fails at compile time@binding/@grouppairing — both required together on resource variablesarray<T, 0>rejected per specstpqrejected, mixed namespaces (v.xg) rejectedvec2<u32>passed asu32now errors (Function argument type missmatch silently compiled #66)Validation parity
All 8 fixes independently verified against Rust naga — identical rejection behavior.
Test plan
go test ./wgsl/ ./ir/— passgo test -run TestRustReference— 100%go test -run TestDxilValSummary— 161/170golangci-lint run --timeout=5m— cleango fmt ./...— clean