# 0071 — global initialized from module const silently zero-initializes > **RESOLVED.** Root cause: `Lowering.registerTopLevelGlobal`'s init_val switch > serialized only literal / array-literal / struct-literal initializers; an > identifier initializer (`g : A = K;`) fell through to `else => null`, so the > global was emitted with no payload and silently zero-initialized. > Fix: extracted the initializer serialization into `Lowering.globalInitValue` > and added an `.identifier` arm that materializes the global's static value from > `ProgramIndex.module_const_map` (typed module consts are registered in the same > pass-2 just before, via `registerTypedModuleConst`). An identifier that names no > usable constant now emits a diagnostic instead of silently zeroing. Other > initializer shapes (enum-literal shorthand, etc.) keep their established > static-lowering behavior — this pass only closes the identifier/module-const > hole. Regression: `examples/0134-types-global-init-from-module-const.sx` > (`g=42` / exit 42). ## Symptom A top-level global initialized from a module constant compiles but is zero-initialized instead of receiving the constant's value. Observed: ```text g=0 ``` Expected: `g` should be initialized to `42`, or the compiler should reject the initializer loudly if identifier/module-const global initializers are not supported. ## Reproduction ```sx #import "modules/std.sx"; A :: B; B :: s32; K : A : 42; g : A = K; main :: () -> s32 { print("g={}\n", g); return g; } ``` Run: ```sh ./zig-out/bin/sx run .sx-tmp/probe-0070-global-init-from-const.sx ``` The repro is standalone; the inline source above is sufficient to recreate the scratch file under `.sx-tmp/`. ## Investigation prompt Fix issue 0071: a top-level global initialized from a module constant must not silently become zero. Context: - This surfaced during Codex re-review of `932cdfa`, the issue-0070 fix. - `932cdfa` correctly defers top-level global and typed-module-const annotation resolution until after the forward-alias fixpoint. - The remaining bug is in the global initializer path, not the annotation path: `K : A : 42; g : A = K;` resolves `A` correctly, registers `K` in `ProgramIndex.module_const_map`, but `g` is emitted as zero. Suspected area: - `src/ir/lower.zig`, `Lowering.registerTopLevelGlobal`. - Its `init_val` switch serializes literal / array / struct-literal initializers, but an identifier initializer falls through to `else => null`, and the global is emitted with no initializer payload. That silently becomes zero-initialized. - Related facts: `ProgramIndex.module_const_map` already records typed module constants via `registerTypedModuleConst`, now in pass 2 after alias convergence. Likely fix: - Add explicit handling for identifier initializers that name a module constant, converting the recorded constant value into the global's `ConstantValue` with the global's declared type. - If some initializer shape cannot be represented as a global constant yet, emit a diagnostic instead of returning `null` / zero-initializing. - Do not regress issue 0070: `A :: B; B :: s32; g : A = 7;` and `K : A : 35;` must still resolve through the converged alias map. - Preserve literal, array literal, struct literal, and foreign-global behavior. Verification: - Add a focused regression, likely in the `01xx` types block: ```sx #import "modules/std.sx"; A :: B; B :: s32; K : A : 42; g : A = K; main :: () -> s32 { print("g={}\n", g); return g; } ``` - Keep these green: - `examples/0133-types-forward-alias-global.sx` - `examples/0132-types-forward-type-alias.sx` - `examples/0116-types-type-alias-size-align.sx` - `examples/0201-generics-generic-struct.sx` - `examples/1117-diagnostics-value-const-as-type-rejected.sx` - Run: ```sh zig build zig build test bash tests/run_examples.sh ``` Expected result: the new regression prints `g=42` and exits `42`; unsupported global initializer shapes no longer silently zero-initialize; the full suite passes.