> **RESOLVED** (NL.2 attempt 4). Root cause: the issue-0092 fix guarded the > numeric-limit intercept against value shadowing using ONLY lexical > `Scope.lookup`. But the ordinary identifier field-access path resolves a > value through THREE sources (`expr_typer.zig` `.identifier` arm): lexical > `scope` → program `global_names` → module value constants > `module_const_map`. A backtick raw identifier bound at MODULE scope > (`` `f64 := Box.{…} ``, a global, or `` `f64 :: Box.{…} ``, a module const) > is registered in `global_names` / `module_const_map`, NOT in `Scope`, so the > scope-only guard missed it and the intercept still folded `` `f64.epsilon `` > to the numeric limit — the same silent-wrong-value bug as 0092, one source > deeper. The module-const variant has the same root cause and is covered by > the same fix (no separate issue). > > Fix (close ALL THREE value-binding sources in one pass): a single shared > helper `Lowering.identifierBindsValue(name)` returns true when `name` > resolves through `scope.lookup` OR `program_index.global_names` OR > `program_index.module_const_map`. Used in BOTH resolvers so they cannot > desync (issue-0083 two-resolver class): > - `src/ir/lower.zig` — `lowerNumericLimit`: defer to ordinary field lowering > (return null) when an `.identifier` receiver `identifierBindsValue`. > - `src/ir/expr_typer.zig` — numeric-limit inference arm: the `shadowed` > check now calls the same helper. > > A bare `f64.epsilon` / `s32.max` (a `.type_expr` receiver, never an > `.identifier`) still folds, even when a global or module-const raw value of > the same spelling exists — the bare receiver is never value-shadowed. > Float-only-on-int and non-numeric-receiver errors are unchanged. > > Regression: `examples/0161-types-numeric-limit-value-shadow.sx` now exercises > all three binding kinds — a GLOBAL `` `f32 ``, a MODULE-CONST `` `s16 ``, and > LOCAL `` `f64 ``/`` `s32 ``/`` `u8 `` — each reading its field while the bare > spelling still folds. Unit test `src/ir/expr_typer.test.zig` pins the global > + module-const sources. NL.1 (`examples/0148`) / NL.2 (`examples/0159`, > `examples/0160`) unregressed. # 0093 — numeric-limit intercept hijacks global raw reserved-spelled value receivers ## Symptom Field access on a **global** raw reserved-spelled value binding is interpreted as a builtin type numeric-limit access instead of an ordinary value field access. Observed: the repro prints `0.000000 2147483647` (`f64.epsilon` / `s32.max`). Expected: it prints `12 78` from the `Box` fields. ## Reproduction ```sx #import "modules/std.sx"; Box :: struct { epsilon: s64; max: s64; } `f64 := Box.{ epsilon = 12, max = 34 }; `s32 := Box.{ epsilon = 56, max = 78 }; main :: () -> s32 { print("{} {}\n", `f64.epsilon, `s32.max); return 0; } ``` ## Investigation prompt Investigate issue 0093: the issue-0092 value-binding precedence fix covers lexical locals but misses global raw value bindings. In `src/ir/lower.zig`, start at `Lowering.lowerNumericLimit` and the new issue-0092 guard around `Scope.lookup`. That guard returns `null` for a shadowing local, but global raw bindings are registered in `ProgramIndex.global_names` (and module constants in `ProgramIndex.module_const_map`), not in `Scope`, so an `.identifier` receiver whose text is `f64` / `s32` still folds to a numeric limit before ordinary global field lowering can read the value. Mirror the same rule in `src/ir/expr_typer.zig` so inferred types match lowering. Likely fix: for `.identifier` numeric-limit receivers, prefer any in-scope value binding source over the builtin-type fold: lexical `Scope.lookup`, global values (`program_index.global_names`), and module value constants where applicable. Keep `.type_expr` receivers folding as type receivers, so bare `f64.epsilon` and `s32.max` still fold even when a raw global value of the same spelling exists. Verification: pin the repro above as a regression. It should print `12 78`. Also verify the existing numeric-limit examples still pass: `examples/0148-types-int-numeric-limits.sx`, `examples/0159-types-float-numeric-limits.sx`, `examples/0160-types-float-numeric-limits-errors.sx`, and `examples/0161-types-numeric-limit-value-shadow.sx`.