Add an .optional arm to regToValue in comptime_vm.zig: read the
has_value flag at offset sizeof(child), bridge the payload recursively
into a { payload, i1=true } aggregate when set, yield .null_val (zero
{T,i1}) when clear or the bare null sentinel. Matching serialize arm in
serializeAggregateValue (emit_llvm.zig). Pointer/?Closure/?Protocol-child
optionals and array-payload aggregates bail loudly, not silently.
Regression: examples/comptime/0643-comptime-run-optional-aggregate.sx
(present ?T, present ?i64, null ?i64). Verified by 3 adversarial reviews.
2.6 KiB
0162 — #run returning an optional aggregate fails the comptime VM reg→value bridge
RESOLVED. Root cause: the comptime VM's
regToValuebridge (src/ir/comptime_vm.zig) had no.optionalarm, so any OPTIONAL-typed#runresult hit the"aggregate shape not bridged yet"bail. Fix: added an.optionalarm that reads the has_value flag (at offsetsizeof(child)), bridges the payload recursively into a{ payload, i1=true }aggregate when set, and yields.null_val(→ zero{T, i1}) when clear or the bare null sentinel; plus a matching serialize arm inserializeAggregateValue(src/ir/emit_llvm.zig). Pointer/?Closure/?Protocol-child optionals and array-payload aggregates bail loudly (out of scope, not silent). Regression test:examples/comptime/0643-comptime-run-optional-aggregate.sx(present?T, present?i64, null?i64). Verified by 3 adversarial reviews.
Symptom
A #run (or comptime const init) whose function returns an OPTIONAL value
(?T, ?i64, any optional) fails comptime evaluation with:
error: comptime init of 'X' failed: reg→value: aggregate shape not bridged yet
A non-optional return of the same type works. This is a pre-existing limitation
in the comptime VM's register→value bridge for optional-typed results; it is
orthogonal to issue 0160 (it reproduces for a value-init optional with no struct
literal anywhere, and for a scalar optional ?i64).
Reproduction
#import "modules/std.sx";
T :: struct { a: i64 = 0; }
mk :: () -> ?T { t : T = .{ a = 7 }; return t; }
mk2 :: () -> ?i64 { return 5; }
X :: #run mk(); // error: reg→value: aggregate shape not bridged yet
Y :: #run mk2(); // same class of failure
main :: () { print("ok\n"); }
Baseline that WORKS: Z :: #run (() -> T { return .{ a = 7 }; })(); (non-optional).
Investigation prompt
src/ir/comptime_vm.zig — the reg→value bridge (search "aggregate shape not
bridged" / regToValue) handles scalars/structs/slices but bails on an
OPTIONAL-typed result. An optional is {payload, has_value} (or a pointer for
?*T / a sentinel for ?Closure); the bridge needs to read the has_value flag
and, when set, bridge the payload as its child type (recursively), producing a
Value optional — and a null optional when clear. Add the .optional arm to
the reg→value bridge (mirror the value→reg direction, which already builds
optionals — see makeStringList/writeField optional handling). Verify with
the repro (expect X/Y to evaluate, main prints ok). Add a
examples/comptime/06xx-... regression.