fix(diagnostics): point reserved-type-name binding errors at the binding (issue 0076)

The reserved-type-name binding diagnostic fired correctly but underlined the
enclosing statement / if / while / for / match / protocol / #objc_class block
because every binding-name check reused the parent `node.span`.

Thread each binding name's own span through the AST and parser, and pass it to
`checkBindingNames`:

- ast: add name spans to VarDecl, DestructureDecl, If/WhileExpr, ForExpr
  (capture + index), MatchArm, Catch/OnFailStmt, Protocol/ForeignMethodDecl.
- parser: populate each span at the binding site from the name token's loc;
  destructure reuses each target identifier's own span.
- semantic_diagnostics: every checkBindingName call now passes the binding's
  own span — no site falls back to node.span. fn/lambda params already used
  Param.name_span.

Carets now land on the offending identifier itself. New regression
examples/1125 asserts the protocol default-body and sx-defined #objc_class
method param spans; 0125/1119-1124 expected updated to the precise carets.
This commit is contained in:
agra
2026-06-03 22:06:56 +03:00
parent fcc76b9391
commit 6433eb6155
15 changed files with 144 additions and 51 deletions

View File

@@ -34,6 +34,17 @@
> function's bindings never reach `Scope.put`, yet they must still be rejected at
> their declaration (e.g. `examples/1119`'s never-called `takes_u8`).
>
> **Span precision (attempt 5).** Every binding form now carries its own
> name span in the AST (`VarDecl.name_span`, `DestructureDecl.name_spans`,
> `IfExpr`/`WhileExpr.binding_span`, `ForExpr.capture_span`/`index_span`,
> `MatchArm.capture_span`, `CatchExpr`/`OnFailStmt.binding_span`,
> `Protocol`/`ForeignMethodDecl.param_name_spans`), populated by the parser at
> each binding site. `checkBindingNames` passes that span to the diagnostic, so
> the caret underlines the offending identifier itself instead of the enclosing
> statement / `if` / `match` / `protocol` / `#objc_class` block. No call site
> falls back to the parent `node.span`. Regular `fn`/lambda params already used
> `Param.name_span`.
>
> **Regression tests:**
> - `examples/0125-types-type-named-var-rejected.sx` — `:=` form (`s2`) rejected.
> - `examples/1119-diagnostics-reserved-type-name-as-identifier.sx` — parameter
@@ -47,6 +58,9 @@
> `onfail` error-tag bindings.
> - `examples/1124-diagnostics-imported-reserved-destructure.sx` — destructure
> name reserved in an IMPORTED module (renders against that module's source).
> - `examples/1125-diagnostics-reserved-name-method-param.sx` — protocol
> default-body method param AND sx-defined `#objc_class` method param, each
> caret landing on the parameter token.
> - `examples/0135-types-self-streaming-nonreserved.sx` — positive: `*self`
> streaming with non-reserved names (`hasher`, `ctx`) accumulates correctly via
> both `update(@h, …)` and `h.update(…)`.