> **RESOLVED (F0.7)** — A typed module-level constant whose initializer does not > match its annotation is now rejected at the declaration with a clear > `type mismatch` diagnostic, killing both symptoms (the `print(N)` segfault and > the `[N]s64` → 4 fold). > > **Root cause.** `registerTypedModuleConst` (`src/ir/lower.zig`) stored the > annotation type on the const but never checked the initializer literal against > it, so `N : string : 4` registered as `{value = int 4, ty = string}`. > `emitModuleConst` then stamped the `int_literal` with the `string` type (a > bogus pointer → segfault at the use site), and `program_index.moduleConstInt` > folded the const into an integer COUNT by inspecting the `int_literal` node > alone, ignoring `ModuleConstInfo.ty` (so `[N]s64` folded to 4). > > **Fix per file.** > - `src/ir/lower.zig` — `registerTypedModuleConst` now validates the > initializer against the resolved annotation via the new `typedConstInitFits` > (arms mirror `emitModuleConst`'s faithful-emit precondition: int → int/float, > float → float, bool → bool, string → string, null → pointer/optional, > `---` → any). A mismatch emits `type mismatch: constant '' is declared > '' but its initializer is ` at the initializer span and does NOT > register the const (it also evicts the pass-0 placeholder so a count use > can't still fold it). `literalKindName` names the literal kind for the > message. > - `src/ir/program_index.zig` — `moduleConstInt` / `moduleConstIntFramed` now > take the `TypeTable` and gate the fold on `isCountableConstType(ci.ty)` > (integer of any width, or a float), so a non-numeric typed const can never be > folded into a count off its initializer node. Callers in `lower.zig` and > `type_bridge.zig` updated. > > **Regression tests.** > - `examples/1143-diagnostics-typed-module-const-mismatch.sx` — negative: four > mismatch shapes (`int→string`, `string→s64`, `bool→s64`, `float→s64`) each > emit a `type mismatch` diagnostic, exit 1. > - `examples/0162-types-typed-module-const-roundtrip.sx` — positive: valid > typed consts (`s64` as count + printed, `f32` from int, `f32` float, > `string`, `*void` null) compile, fold, and print correctly. > - `src/ir/program_index.test.zig` — `moduleConstInt gates the fold on the > declared type, not the initializer node`. # 0088 — Typed module const annotation mismatch is accepted ## Symptom A module-level typed constant whose initializer does not match its annotation is accepted. Observed: `N : string : 4` compiles; printing `N` segfaults, and using `N` as an array dimension folds it as `4`. Expected: the const declaration emits a type-mismatch diagnostic and no downstream use treats it as a valid string or integer count. ## Reproduction ```sx #import "modules/std.sx"; N : string : 4; main :: () { print("N={}\n", N); } ``` Related count-surface manifestation: ```sx #import "modules/std.sx"; N : string : 4; main :: () { a : [N]s64 = ---; print("{}\n", a.len); } ``` Observed on `flow/sx-foundation/F0.4` attempt 10: the first repro segfaults in the generated program; the second prints `4`. ## Investigation prompt Fix issue 0088: typed module constants must validate/coerce their initializer against the explicit annotation before being registered or used. Suspected area: `src/ir/lower.zig`, especially `registerTypedModuleConst`, `lowerExpr`'s module-const identifier path, and any const-declaration lowering that stores `ProgramIndex.module_const_map` entries. `src/ir/program_index.zig`'s `moduleConstInt` currently folds by inspecting the initializer node and ignores `ModuleConstInfo.ty`; after the declaration is diagnosed or represented correctly, a non-integer typed const such as `N : string : 4` must not become a valid count. Likely fix: add a typed-const validation path that emits a clear diagnostic for incompatible initializer/annotation pairs, and ensure the module-const count lookup only accepts constants whose declared/inferred type is numeric and integral-compatible. Verify by running the two repros above: expect a non-zero compile with a type-mismatch diagnostic for `N : string : 4`, no runtime segfault, and no `[N]` length of `4`.