Files
sx/issues/0117-pointer-to-array-index-unresolved-panic.md
agra 82d6b8da0e fix(0117): pointer-to-array indexing auto-derefs
A '*[N]T' receiver in an index expression reached LLVM emission with an
unresolved element type and tripped the panic sentinel — no read or
write spelling worked. ptrToArrayElem on Lowering recognises the shape;
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). Kept out of getElementType so slice paths don't half-accept a
raw pointer base.

Regression: examples/0176 (read, write, compound, element ptr + deref).
2026-06-11 12:15:45 +03:00

63 lines
2.8 KiB
Markdown

# 0117 — indexing through a pointer-to-array panics at LLVM emission
> **RESOLVED** (2026-06-11). `ptrToArrayElem` on Lowering recognises the
> `*[N]T` receiver; 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, via `emitIndexGet`).
- **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]T` is
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
```sx
#import "modules/std.sx";
main :: () {
k : [4]s64 = .[11, 22, 33, 44];
p := @k; // *[4]s64
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.