Files
sx/examples/0761-modules-same-name-const-expr-chain-dim.sx
agra 8518b66cec fix(lower): propagate source-aware const selection into expression-chain folds — close F2 R1 [stdlib E2 attempt-4]
attempt-3 made the value-const READ source-aware (own-wins / ambiguous) but
the dimension/count fold of a SELECTED const's RHS still recursed through the
global last-wins `module_const_map`, so a nested same-name leaf came from the
wrong module. Reviewer R1: a.sx `M::1; K::M+1`, b.sx `M::10; K::M+1`, with both
`[K]u8` (a_len) and `return K` (a_val) — pre-fix `a_len=11 a_val=2`, an
INCOHERENCE for the same const `K` (a_val read A's chain; a_len read B's `M`).

`comptimeIntNamed` delegated to `moduleConstIntWith(global_map, ...)`, whose
leaf ctx (`ModuleConstCtx`) resolved nested names through the global map. The
value path (`emitModuleConst` -> `foldCountI64(ci.value, self)`) folds through
`self`, so its leaves bounce back to the source-aware `comptimeIntNamed` — which
is why a_val was already correct.

- New `SourceConstCtx` (lower.zig): the leaf-resolution twin of `ModuleConstCtx`,
  but every nested const leaf re-selects its OWN source author via
  `selectModuleConst` (own-wins / ambiguous), never the global last-wins map.
  `ConstFoldFrame` cycle-guards a const whose RHS references another const.
- `comptimeIntNamed` / `lookupFloatName` / `nameIsFloatTyped` now fold the
  selected `ci`'s RHS through `SourceConstCtx` (via `foldSourceConstInt` /
  `foldSourceConstFloat` / `sourceConstIsFloatTyped`). This makes the dimension
  and value reads of a shadowed expression-chain const coherent.
- Drop the now-unused `moduleConst{Int,Float,IsFloatTyped}With` wrappers from
  program_index.zig; expose `isCountableConstType` / `isFloatConstType`.

Single-author -> byte-identical (the selected `ci` IS the global one and every
nested leaf has one author). The stateless `type_bridge` registration-time const
reader still folds leaves through the global map, but realistic dim sites (struct
fields, array aliases — probed) resolve via the stateful path and stay coherent
under import-order swaps; no reachable wrong-dimension found (tracked follow-up,
byte-identical single-author).

Regression: examples/0761-modules-same-name-const-expr-chain-dim — a_len=2
a_val=2, b_len=11 b_val=11. Fail-before on 72f06a1 (`a_len=11`), pass-after.

Gate: zig build + zig build test (423/423, LSP sweep 515 clean) + run_examples
(499/0, 498 prior byte-identical + 0761) + m3te ios-sim build exit 0.
2026-06-08 01:06:44 +03:00

20 lines
1.0 KiB
Plaintext

// issue 0105 / F2 — same-name const EXPRESSION CHAIN, coherent across a value
// read AND an array dimension. Two flat-imported modules each declare a same-name
// `M` and a same-name `K :: M + 1` that reads `M`. Each module uses ITS OWN `K`
// both as a runtime value (`return K`) and as an array dimension (`[K]u8`).
//
// The fold of a SELECTED const's RHS must resolve nested same-name leaves (the
// `M` inside `K :: M + 1`) in the SELECTED author's source context, not through
// the global last-wins `module_const_map`. Pre-fix (72f06a1) the dimension fold
// recursed through the global map, so `a_len` read B's `M` (= 11) while `a_val`
// correctly read A's chain (= 2) — an INCOHERENCE for the same const `K`. Now
// both observables agree per module: a_len=2 a_val=2, b_len=11 b_val=11.
#import "modules/std.sx";
#import "0761-modules-same-name-const-expr-chain-dim/a.sx";
#import "0761-modules-same-name-const-expr-chain-dim/b.sx";
main :: () -> s32 {
print("a_len={} a_val={} b_len={} b_val={}\n", a_len(), a_val(), b_len(), b_val());
0
}