Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
2.8 KiB
0117 — indexing through a pointer-to-array panics at LLVM emission
RESOLVED (2026-06-11).
ptrToArrayElemon Lowering recognises the*[N]Treceiver; the index READ path GEPs the pointee array through the pointer value and loads the element; the WRITE / compound-assign / lvalue / addr-of-element paths and the expression typer resolve the element type through the same helper (their GEP machinery already handled a pointer base). Postfix deref (p.*) was always the deref spelling — the issue's(*p)[2]note was a wrong-syntax red herring. Regression test: examples/0176-types-pointer-to-array-index.sx (read, write, compound, element pointer + deref).
Symptom. Indexing through a *[N]T pointer is neither lowered nor
diagnosed: the index expression reaches the LLVM emitter with the
.unresolved type sentinel and trips the panic tripwire.
- Observed:
panic: unresolved type reached LLVM emission(src/backend/llvm/types.zig:175, viaemitIndexGet). - Expected: either
p[2]auto-derefs the pointer-to-array (load the pointer, GEP into the array — mirroring the field-access auto-deref on struct pointers), or a clean diagnostic if indexing through*[N]Tis out of spec. Never an emit-time panic.
Pre-existing — reproduces on plain locals with no module-level features
involved (found while pinning @K reads for PLAN-CONST-AGG step 1; the
same panic fires for @<var-decl global array> and @<array const>).
Also note: the explicit-deref spelling (*p)[2] does not parse as a
deref — it lowers as unknown_expr ("unresolved 'unknown_expr'"), so
there is no working spelling for reading an element through a
pointer-to-array.
Reproduction
#import "modules/std.sx";
main :: () {
k : [4]i64 = .[11, 22, 33, 44];
p := @k; // *[4]i64
print("{}\n", p[2]); // expected 33; panics at emission today
}
Investigation prompt
emitIndexGet receives an index_get whose result type is .unresolved
— the lowering of index_expr over a receiver of pointer-to-array type
produces no deref. Suspected area: the index lowering in
src/ir/lower/expr.zig (lowerIndexExpr or equivalent — find the
index_expr arm) and its typing twin in src/ir/expr_typer.zig: both
handle array / slice / many-pointer receivers but not
pointer → array. The fix likely mirrors the struct-pointer auto-deref:
when the receiver type is .pointer whose pointee is .array, load the
pointer value and index the pointee array (element type = pointee
element), in BOTH the typer and the lowering. Check the assignment-target
path too (p[1] = v through a pointer-to-array).
Verification: the repro above prints 33; add a pin under
examples/01xx-types-… covering read AND write-through
(p[1] = 5; print k[1] → 5 for a mutable local). Suite + zig build test
stay green.