feat(lang): raw provenance through ALL sema compound type metadata — finish universal raw identifier in the LSP classifier [F0.6]

The codegen-side resolver was already raw-aware for the universal model;
the sema/LSP editor index (the second classifier) only honored the DIRECT
raw type. A COMPOUND raw type (`*`s2`, `?`s2`, `[N]`s2`, `[]`s2`, `[*]`s2`)
stores its inner type-name as a bare string on the Type info struct, and
every resolution site re-read it with skip_builtin=false — so the index
reclassified a user type named `s2` as the builtin int, diverging from
codegen (issue-0083 class, LSP surface only; codegen unchanged).

Structural cure: every compound info struct (Pointer/Optional/Slice/
ManyPointer/Array) carries a REQUIRED is_raw bit (no default — a future
construction site cannot drop it). is_raw is set at every construction
site (resolveTypeNode arms, fieldType arms, variadic slice, .ptr/slice_expr
derivation, for-loop by-ref, substType) and passed as skip_builtin at every
resolution site (elementTypeOf, field-access pointer unwrap, index, deref,
optional unwrap/null-coalesce, if/while optional binding, match subject).
Optional-unwrap + deref sites converted from Type.fromName/pointerPointeeType
(builtin-only, divergent) to resolveTypeNameStr(name, is_raw); the now-dead
pointerPointeeType removed.

Tests: src/sema.test.zig gains pointer/optional/array raw-vs-bare
regressions (raw → user type, bare → builtin control) — each FAILS on
pre-fix sema, PASSES after — plus a parameterized-raw coverage test.
This commit is contained in:
agra
2026-06-04 21:46:31 +03:00
parent ef8f021c01
commit 724a919fc1
4 changed files with 223 additions and 48 deletions

View File

@@ -35,7 +35,15 @@
> builtin int. The SECOND (editor/LSP) classifier in [src/sema.zig]
> (`Type.fromTypeExpr` / `resolveTypeNode` / `resolveTypeNameStr`) honors
> `is_raw` too, so a backtick reserved-name annotation resolves to the user type
> in hover/completion, not the builtin (no two-resolver divergence).
> in hover/completion, not the builtin (no two-resolver divergence). The raw bit
> is carried STRUCTURALLY through every COMPOUND shape's inner-name metadata —
> `PointerTypeInfo` / `OptionalTypeInfo` / `SliceTypeInfo` / `ManyPointerTypeInfo`
> / `ArrayTypeInfo` each store a REQUIRED `is_raw` ([src/types.zig], no default,
> so a future construction site cannot drop it) that every `resolveTypeNameStr`
> call passes as its `skip_builtin` — so `` *`s2 ``, `` ?`s2 ``, `` [N]`s2 ``,
> `` []`s2 ``, `` [*]`s2 `` field-access / unwrap / index / deref in the editor
> index all reach the user type instead of reclassifying the inner `s2` to the
> builtin (the divergence the DIRECT-only attempt left for compound forms).
> - **Declaration position.** A bare reserved-name declaration of EVERY kind
> still errors (issue 0076 preserved); the backtick form is exempt. The check
> and the exemption are made structurally symmetric:
@@ -82,7 +90,10 @@
> `examples/1142-diagnostics-reserved-name-struct-const.sx` (bare struct-body const,
> caret on the name). Backtick lexer + `resolveNamed(skip_builtin)` unit tests in
> `src/lexer.zig` / `src/ir/type_resolver.test.zig`; the editor/LSP raw-type
> resolution (the second classifier) is pinned in `src/sema.test.zig`.
> resolution (the second classifier) is pinned in `src/sema.test.zig` — the direct
> case plus raw provenance through every compound shape (`` *`s2 `` field access,
> `` ?`s2 `` unwrap, `` [N]`s2 `` index, parameterized `` `s2(s64) ``), each with a
> bare-spelling control that stays the builtin (fail-before verified).
>
> The original report is preserved below.