(C) regToValue (comptime_vm.zig) gained no array arm, so a #run returning an aggregate containing an array bailed 'reg->value: aggregate shape not bridged yet'. Add an .array arm: read N elements at stride typeSizeBytes(elem) from the array address, bridge each recursively via regToValue -> an .aggregate Value (serializeAggregateValue already emits arrays). Composes with struct fields, nested arrays, array-of-structs, and the ?Arr optional payload; unbridgeable elements bail loudly. (E) A global failing #run proceeded into LLVM emission and panicked 'unresolved type reached LLVM emission' when the unresolved const was used. Add 'if (self.comptime_failed) return;' in emit() after Pass 0 so it aborts cleanly (exit 1, the comptime diagnostic) across run/ir/build. Regression: examples/comptime/0644-comptime-run-array-aggregate.sx. Verified by 3 adversarial reviews, suite 793/0. Filed separate bugs found during review: 0181 (optional-chain ?. to array field + index panics), 0182 (body-local #run unbridged silently miscompiles).
3.8 KiB
0181 — ?.-chain (and ?-postfix) on an optional whose child struct contains an ARRAY field panics unresolved type reached LLVM emission
Symptom
A ?. optional-chain access (or the ? optional-test postfix used in a
member-access chain) on a value of type ?S, where S is a struct that
contains an array field, panics:
thread … panic: unresolved type reached LLVM emission — a type resolution failure was not diagnosed/aborted (exit 134).
The same chain on ?S where S has no array field works fine, and the
! force-unwrap chain (opt!.field) on the same array-containing ?S works
fine. The defect is specific to the ?/?. operator's receiver-type inference
when the optional's child struct contains an array field — that receiver types
as .unresolved and reaches LLVM. This is a pure runtime lowering bug: no
#run/comptime is involved.
Observed vs expected:
- Observed: SIGABRT panic (exit 134) at
src/backend/llvm/types.zig:196(toLLVMTypeInfo.unresolvedarm), reached fromdeclareFunction'sparam.tylowering of a synthesized accessor. - Expected: the chain evaluates (prints the field), exactly as the
!-unwrap and the non-array?.forms already do.
Reproduction
Pure runtime, no #run — panics:
#import "modules/std.sx";
Arr3 :: struct { xs: [3]i64; }
mk :: () -> ?Arr3 { r : Arr3 = .{ xs = .[1,2,3] }; return r; }
main :: () { print("{}\n", mk()?.xs[0] ?? 99); } // PANIC exit 134
Control A — same chain, child struct has NO array field — WORKS, prints 7:
#import "modules/std.sx";
Pt :: struct { x: i64; }
mk :: () -> ?Pt { return Pt.{ x = 7 }; }
main :: () { print("{}\n", mk()?.x ?? 99); }
Control B — same array-containing ?Arr3, but ! force-unwrap — WORKS, prints 1:
#import "modules/std.sx";
Arr3 :: struct { xs: [3]i64; }
mk :: () -> ?Arr3 { r : Arr3 = .{ xs = .[1,2,3] }; return r; }
main :: () { print("{}\n", mk()!.xs[0]); }
(The issue 0167 (E) repro A?.xs[0] hit this same bug — it used ? where !
was meant; with ! the comptime #run ?Arr3 case evaluates. So this is the
residual defect that 0167's (E) repro tripped, distinct from 0167 (C)/(E),
both of which are fixed.)
Investigation prompt
The ? optional-chaining / optional-test path synthesizes an accessor whose
receiver (the unwrapped child) types as .unresolved specifically when the
child is a struct containing an array field — mirroring the already-fixed
issue-0101 !-unwrap bug (inferExprType had no force_unwrap arm → receiver
typed .unresolved). The ! path was fixed (see
examples/optionals/0905-optionals-unwrap-field-chain.sx); the ?/?. path
has an analogous gap that only surfaces for an array-containing child (a
plain-scalar/string child happens to resolve).
Suspected area: src/ir/lower.zig inferExprType (grep for the optional-chain
/ ? postfix / safe_nav handling) and/or src/ir/lower/ accessor-chain
lowering — find where the ?-chain receiver type is computed and why an
array-containing struct child yields .unresolved. Compare against the working
!-unwrap arm (issue 0101 fix) and apply the same receiver-type flow.
Verification: the first repro above prints 1 and exits 0; controls A and B
still pass; add a regression under examples/optionals/ covering ?.-chain on
an array-containing ?S (field read + ?? default). Confirm
examples/comptime/0644-comptime-run-array-aggregate.sx (issue 0167) still
passes.
Provenance
Discovered while implementing issue 0167 (C: comptime reg→value array-in-
aggregate bridge; E: clean-abort on comptime-init failure). 0167 (C) and (E)
are FIXED and verified; the ?Arr3 access form in 0167's (E) repro tripped this
SEPARATE, pre-existing runtime lowering bug (confirmed reproducible on clean
HEAD with no #run).