lowerIndexExpr fell through to an index_get with an .unresolved element
type for any non-indexable object (*T, *[]T, struct, scalar), reaching
codegen -> 'unresolved type reached LLVM emission' panic. Add a guard
after all indexable arms: if getElementType(obj_ty) is .unresolved and
obj_ty is itself resolved (genuinely non-indexable, not a prior-error
placeholder), emit a located 'cannot index a value of type <T>'
diagnostic + placeholder (hasErrors aborts before codegen). A single
pointer hints by pointee: ptr-to-scalar -> many-pointer/dereference;
ptr-to-array/slice -> dereference first. No false-positives (generics,
aliases, late-resolved, every indexable shape verified).
Regression: examples/diagnostics/1203-diagnostics-index-non-indexable.sx.
Verified by 3 adversarial reviews, suite 799/0. Filed adjacent pre-existing
panic 0184 (untyped positional .{ } literal with no target type).
3.4 KiB
0183 — indexing a non-indexable type (*T, *[]T, struct, …) panics instead of a clean diagnostic
RESOLVED.
lowerIndexExpr(src/ir/lower/expr.zig) fell through to anindex_getwith an.unresolvedelement type for any non-indexable object, reaching codegen → panic. Added a guard after all indexable arms: ifgetElementType(obj_ty)is.unresolvedandobj_tyis itself resolved (so a genuinely non-indexable type, not a prior-error placeholder), emit a locatedcannot index a value of type '<T>'diagnostic and return a placeholder (hasErrors()aborts before codegen). A single pointer hints by pointee: pointer-to-scalar → "use a many-pointer[*]T, or dereference first"; pointer-to-array/slice → "dereference first ((*p)[i])". No false-positives — generics, type aliases, late-resolved objects, and every indexable shape ([N]T/[]T/[*]T/string/Vector/*[N]T/optional-chain) still work (verified by 3 adversarial reviews; suite 799/0). Regression:examples/diagnostics/1203-diagnostics-index-non-indexable.sx. (Adjacent pre-existing panic found + filed: 0184 — an untyped positional.{ }literal with no target type panics; the guard correctly defers on it.)
Symptom
expr[i] where expr's type is not array / slice / many-pointer / string —
e.g. a single-element pointer *T, a pointer-to-slice *[]T, or a struct — does
NOT emit a type error. It falls through lowerIndexExpr to an index_get with an
.unresolved element type and reaches codegen, panicking unresolved type reached LLVM emission (exit 134). Pure runtime, no optionals/comptime. ([*]T
many-pointers and [N]T/[]T/string ARE indexable and unaffected.)
Found during adversarial review of issue 0181 (the optional-chain index fix); the
same fall-through underlies the ?*[]T/?*T/?struct chain-index panics, but it
reproduces identically WITHOUT optional chaining, so it is a separate, broader
gap in the index lowering.
Reproduction
#import "modules/std.sx";
main :: () {
x := 5;
p : *i64 = @x;
print("{}\n", p[0]); // panic: unresolved type reached LLVM emission, exit 134
}
Also panics: indexing a *[]i64 (pointer-to-slice), indexing a plain struct
value. Expected: a located diagnostic, e.g. error: cannot index a value of type '*i64' (use a many-pointer '[*]T', or dereference first), exit 1.
Investigation prompt
src/ir/lower/expr.zig lowerIndexExpr: after the array / slice / many-pointer /
string / optional-chain dispatch arms, the fall-through emits index_get with
getElementType(obj_ty) even when that is .unresolved. Add a final guard: if
the object type is not indexable (element type resolves to .unresolved and the
type isn't a recognized indexable shape), emit
self.diagnostics.addFmt(.err, span, "cannot index a value of type '{s}'", .{...})
and return a placeholder — never emit an index_get with an unresolved element
type. Mirror the located-diagnostic + placeholder pattern used elsewhere in the
lowering. The static typer (src/ir/expr_typer.zig index_expr) should likewise
yield .unresolved (already does) so this is the single choke point. Follow the
no-silent-fallback rule (here it's a loud PANIC, which must become a clean
diagnostic). Verify: the repro exits 1 with the diagnostic; [*]T/[]T/[N]T/
string/optional-chain indexing all still work. Add an
examples/diagnostics/12xx-index-non-indexable.sx negative regression.