# 0080 - global array of struct literals silently zero-initializes > **RESOLVED.** > **Root cause:** `Lowering.constExprValue` (`src/ir/lower.zig`) — the constant- > aggregate serializer for global initializers — handled primitive and nested- > array leaves but had **no `.struct_literal` arm**. A module-global `[N]Struct` > initialized with struct literals reached `constArrayLiteral` → `constExprValue` > per element; each struct-literal element returned `null`, collapsing the whole > array initializer to `null`. `globalInitValue` then emitted no payload, so the > LLVM backend zero-initialized the global (`@pairs = ... zeroinitializer`), > silently dropping every declared field — the same silent-zero class as > 0071/0072, one level inside an array literal. (A global *struct* literal and a > *struct-with-array* already worked, because `constStructLiteral` existed and was > reached directly; the gap was specifically struct literals *as array elements*.) > **Fix:** make `constExprValue` type-aware — thread the destination element/field > `TypeId` so a `.struct_literal` leaf routes through `constStructLiteral` and a > nested `.array_literal` through `constArrayLiteral` with the correct element > type. `constArrayLiteral` derives its element type from the array `TypeId`; > `constStructLiteral` passes each field's type. A global aggregate initializer > that still does not fully reduce to a compile-time constant is now **rejected > loudly** (`diagnoseNonConstGlobal`) instead of falling through to a zeroed > global. The downstream `emitConstAggregate` already recurses over nested > aggregates, so const/AOT (`sx build`) and JIT (`sx run`) both materialize the > declared values. > **Regression:** `examples/0137-types-global-aggregate-literal-init.sx` (global > `[N]Struct` literal, global struct literal, struct-with-array, nested array-of- > struct-with-array; values read back with no prior store, plus a store on top). > FAILS on the pre-fix compiler (array-of-struct fields read 0), PASSES after. ## Symptom A module-global fixed array whose elements are struct literals is emitted as zero-initialized storage instead of preserving the literal fields. Observed: reading `pairs[0].b` and `pairs[1].a` prints `0`. Expected: the global should contain the declared struct literal values (`2` and `3`), or the compiler should reject the initializer loudly if this constant shape is unsupported. ## Reproduction ```sx #import "modules/std.sx"; Pair :: struct { a: s64; b: s64; } pairs : [2]Pair = .[ .{ a = 1, b = 2 }, .{ a = 3, b = 4 } ]; main :: () -> s32 { print("pairs[0]={},{}\n", pairs[0].a, pairs[0].b); print("pairs[1]={},{}\n", pairs[1].a, pairs[1].b); if pairs[0].a == 1 and pairs[0].b == 2 and pairs[1].a == 3 and pairs[1].b == 4 { print("PASS\n"); return 0; } print("FAIL: global array struct literal initializer zeroed\n"); return 1; } ``` On the current compiler this prints: ```text pairs[0]=0,0 pairs[1]=0,0 FAIL: global array struct literal initializer zeroed ``` `sx ir ` shows the global as: ```llvm @pairs = internal global [2 x { i64, i64 }] zeroinitializer ``` ## Investigation prompt Fix issue 0080: a module-global array initialized with struct literal elements silently becomes `zeroinitializer`. Suspected area: - `src/ir/lower.zig`, `Lowering.globalInitValue`. - `src/ir/lower.zig`, `Lowering.constArrayLiteral`. - `src/ir/lower.zig`, `Lowering.constExprValue`. - `src/ir/lower.zig`, `Lowering.constStructLiteral`. Likely root cause: `globalInitValue` handles a top-level `.array_literal` by calling `constArrayLiteral`, and `constArrayLiteral` serializes each element via `constExprValue`. `constExprValue` handles primitive literals and nested arrays, but not `.struct_literal`, so an array whose element is a struct literal returns `null`. That null initializer payload is later emitted as zero-initialized storage, recreating the silent zero pattern from issues 0071/0072 one level inside an otherwise-supported array literal. Likely fix: - Thread the expected element `TypeId` into `constArrayLiteral`, or otherwise make `constExprValue` type-aware for struct literals. - Serialize each struct element through `constStructLiteral` with the array's element type. - If any element shape is still unsupported, emit a diagnostic naming the global instead of returning `null` and allowing zero-initialization. Verification: - Run the repro above and expect: ```text pairs[0]=1,2 pairs[1]=3,4 PASS ``` - Add a pinned regression in the `01xx` types block. - Run: ```sh zig build zig build test bash tests/run_examples.sh ```