The reserved/builtin-type-name binding diagnostic was a hand-walked subset
of binding-bearing AST nodes with a silent `else => {}`, so each review
found another syntactic binding form that bypassed it and hit the original
LLVM verifier abort: destructure names (`s2, x := …`), `impl` method
params/locals, and `if` / `while` / `for` / match-arm / `catch` / `onfail`
captures.
Rewrite `checkBindingNames` (src/ir/semantic_diagnostics.zig) as an
EXHAUSTIVE `switch` over every `Node.Data` tag with NO `else` arm — a future
binding-bearing node type now fails to compile until it is handled here, so
coverage is enforced by the compiler instead of a hand-maintained list. The
check stays in the pre-lowering semantic pass rather than moving to the
`Scope.put` scope-registration choke point: lowering is lazy, so an
uncalled function's bindings never reach `Scope.put`, yet they must still be
rejected at their declaration (e.g. the never-called `takes_u8` in 1119).
No lowering special-case; `lower.zig` unchanged.
Regression tests (fail-before: LLVM abort or silent accept → pass-after:
clean diagnostic, exit 1):
- 1121 control-flow: destructure, if/while bindings, for capture+index,
match-arm capture
- 1122 impl-block method: reserved param AND reserved local
- 1123 catch + onfail tag bindings
- 1124 destructure name reserved in an imported module
Existing 0125 / 1119 / 0135 / 1120 tests kept; full suite 368 passed.
31 lines
1.0 KiB
Plaintext
31 lines
1.0 KiB
Plaintext
// A reserved/builtin type name is rejected as a binding name inside an `impl`
|
|
// block's method too — both as a parameter (`u8`) and as a local (`s2`). The
|
|
// impl method is reached through the exhaustive binding-name walk's
|
|
// `impl_block` arm (→ each method's `fn_decl`), so an `impl` method is no more
|
|
// exempt than a free function. Without the diagnostic the reserved local's
|
|
// `@s2` mis-lowers (a loaded aggregate passed by value to a `*Box` param →
|
|
// LLVM verifier abort).
|
|
//
|
|
// Regression (issue 0076, attempt-4 coverage). Expected: one error for the
|
|
// param and one for the local; exit 1.
|
|
#import "modules/std.sx";
|
|
|
|
Box :: struct { total: s64 = 0; count: s64 = 0; }
|
|
update :: (self: *Box, n: s64) { self.total += n; self.count += 1; }
|
|
|
|
Doer :: protocol { go :: (self: *Self, n: s64); }
|
|
|
|
impl Doer for Box {
|
|
go :: (self: *Box, u8: s64) {
|
|
s2 := Box.{ total = 1 };
|
|
update(@s2, u8);
|
|
self.total += s2.total;
|
|
}
|
|
}
|
|
|
|
main :: () -> s32 {
|
|
b := Box.{};
|
|
b.go(7);
|
|
return 0;
|
|
}
|