Harden semantic validation and preserve source diagnostics - #332
Merged
Conversation
Replace the minimal string-based verifier with a program-aware semantic validation pass that rejects invalid Wave programs before they reach LLVM code generation. Semantic and type-system changes: - collect functions, externs, globals, aliases, structs, enums, methods, and generic declarations before validating bodies - reject duplicate top-level symbols, local bindings, fields, variants, methods, aliases, parameters, and declarations in the same scope while preserving nested shadowing - validate unknown, void, pointer, array, named, alias, struct, enum, and generic types in declarations, signatures, casts, fields, and expressions - enforce function return contracts, missing-return detection, void-value restrictions, loop-only break and continue, and call argument compatibility - support default parameters and generic function, struct, field, and method type substitution without regressing pre-monomorphization validation - reject incorrect generic arity early, including errors originating in imported source files - require mutable lvalues for input and mutation, validate assignment and compound-assignment operands, and reject unsupported increment and decrement operations - validate explicit casts, contextual array literals, addressed arrays, integer literal ranges, pointer and integer conversions, and float width conversions - reject duplicate match constants by their evaluated numeric value and enforce consistent mixed-width floating-point semantics - reject aggregate formatting until a defined formatter contract exists while retaining scalar, string, pointer, and null formatting Structured diagnostic and import provenance changes: - add SemanticDiagnostic with a stable error code, message, top-level node index, primary span hint, label, note, and help text - retain the legacy string-returning parser API as a compatibility wrapper around detailed diagnostics - preserve imported source text and associate every expanded top-level AST node with its original source unit - validate the expanded AST before generic monomorphization so user-facing semantic failures retain their original source location - replace message parsing and heuristic substring lookup with structured declaration, keyword, and identifier span hints - scope occurrence resolution to the relevant top-level node so repeated identifiers, repeated returns, and duplicate declarations point at the actual failing occurrence - report semantic failures in imported modules against the imported path, line, column, and highlighted source span instead of the entry file at 1:1 LLVM and control-flow fixes: - stop emitting statements after a basic block already has a terminator - mark unreachable merge blocks and provably non-breaking infinite-loop exits as unreachable - use implicit coercion rules for return lowering after semantic validation has established compatibility - add explicit floating-point widening and narrowing emission with LLVM float casts Regression and corpus updates: - add integration coverage for invalid returns, missing returns, loop control, calls, casts, lvalues, duplicate symbols, unknown and void types, array contexts, integer truncation, match duplicates, formatting, float widths, generics, and diagnostic source locations - verify check and build reject the same invalid programs before backend panics or E9001 failures - cover repeated local and return locations, duplicate top-level declarations, imported unknown types, and imported generic arity diagnostics - update TCP and overflow examples to use explicit narrowing casts and avoid formatting an aggregate without a formatter - ignore the local .tmp planning directory Validation completed: - cargo fmt --all -- --check - cargo test --locked --all-targets: 15 tests passed - cargo clippy --locked --all-targets -- -D warnings - cargo build --locked --release - Wave end-to-end suite: 96 passed, 12 environment or architecture skips, 0 failed - all 13 examples passed wavec check - all 79 standard-library modules passed wavec check - git diff --check
Make compiler integration tests deterministic when GitHub Actions enables colored Cargo output. All test helpers now launch wavec with NO_COLOR=1, preventing ANSI styling from splitting diagnostic tokens such as error[E3001] and causing valid semantic-diagnostic assertions to fail on Linux and macOS runners. Expose the tested host architecture directly in each workflow check name: - rename build-ubuntu to build-linux-amd64 - rename build-macos to build-macos-arm64 - rename build-windows to build-windows-amd64 Repair Windows toolchain provisioning after the current MSYS2 package database stopped resolving the versioned llvm-21 and lld-21 package names through pacman -S. Keep the regular runtime dependencies in setup-msys2 and install the official LLVM 21.1.8-5 and LLD 21.1.8-5 packages from pinned MSYS2 mirror URLs so the llvm-sys 21 contract and /mingw64/opt/llvm-21 layout remain stable. Validation: - reproduced the GitHub runner environment with NO_COLOR unset and CARGO_TERM_COLOR=always - cargo test --locked --all-targets: 15 tests passed - cargo fmt --all -- --check - cargo clippy --locked --all-targets -- -D warnings - parsed .github/workflows/rust.yml successfully - verified both pinned MSYS2 package URLs return HTTP 200 - git diff --check
LunaStev
marked this pull request as ready for review
August 8, 2026 10:33
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
This change replaces Wave's minimal string-based semantic verifier with a program-aware validation pass that rejects invalid programs before LLVM code generation. It also introduces structured semantic diagnostics with source provenance so errors point to the actual declaration, expression, or imported file that caused the failure.
The work is the prerequisite semantic-validation gate for the v0.2.1-pre-beta RISC-V effort. RISC-V backend failures cannot be diagnosed reliably while invalid source programs are still accepted by
wavec check, lowered differently bywavec build, or reported as backend panics.Semantic validation
breakandcontinueoutside loops.inputand mutation operations.Structured diagnostics and source provenance
SemanticDiagnosticwith an error code, message, top-level node index, primary span hint, label, note, and help text.returnstatements, duplicate declarations, and other repeated syntax.1:1.LLVM and control-flow fixes
Regression coverage and corpus updates
wavec checkandwavec buildreject the same invalid source before a backend panic or E9001 failure can occur..tmpplanning directory.User and developer impact
Invalid Wave programs now fail earlier with actionable semantic diagnostics instead of reaching target-specific LLVM lowering. Diagnostics remain attached to the original imported source, and valid programs using defaults or generics continue to pass validation. This establishes a stable frontend baseline for distinguishing language errors from upcoming RISC-V ABI, code generation, linking, and runtime issues.
Validation
cargo fmt --all -- --checkcargo test --locked --all-targets— 15 tests passedcargo clippy --locked --all-targets -- -D warningscargo build --locked --releasewavec checkwavec checkgit diff --check