From ca8ffe8dc3425fe1102a7569e08a2293328f2e5b Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 10 May 2026 01:12:11 +0200 Subject: [PATCH] =?UTF-8?q?journal:=20bug=20fix=20=E2=80=94=20mono=20pass?= =?UTF-8?q?=20env.globals=20seeding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/JOURNAL.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md index 3d1dc8c..4af6fb3 100644 --- a/docs/JOURNAL.md +++ b/docs/JOURNAL.md @@ -11912,3 +11912,61 @@ compile today. RED-first debug iter follows. **Action items spawned by this iter:** - RED-first debug iter for the `env.globals` mono bug. + +## 2026-05-10 — Bug fix: mono-pass `env.globals` not seeded — recursive top-level fn in class workspace + +Surfaced by the mono-vs-vdisp bench (entry above). RED-first per +`skills/debug` discipline; one RED-test commit, one GREEN-fix commit. + +**Symptom.** `ail build` on a workspace containing one `Def::Class`, +one `Def::Instance`, and a self-recursive top-level `Def::Fn` +exits with `monomorphise_workspace: unknown identifier `. +`ail check` on the same fixture passes — proof that the typechecker +is fine and the gap is in the mono pass. + +**Cause.** `crates/ailang-check/src/mono.rs::collect_mono_targets` +(line 463) and `collect_residuals_ordered` (line 819) both +re-run `crate::synth` on a fn body to recover residual class +constraints, but their `env` (built by `build_workspace_env`) only +populates `module_globals` (per-module index) — not `globals` (the +flat current-module table that `synth`'s `Term::Var` lookup at +lib.rs:1678 actually reads). The main check path handles this at +lib.rs:1135-1139, seeding `env.globals` per module before `synth` +runs; mono.rs did not. Sibling gap to commit 5c5180f's +`env.types` / `env.ctor_index` fix from milestone 22c — same +shape, different env table. + +**Fix.** Two-line seed in each of the two `synth`-rerun call +sites: `if let Some(g) = env.module_globals.get(module_name).cloned() { for (n, t) in g { env.globals.insert(n, t); } }`. +Per-module scope (not workspace-wide), because top-level fn names +are only per-module-unique — `build_module_globals` +(lib.rs:1011-1019) enforces uniqueness within a module, not +workspace-wide. A flat workspace seed would silently shadow +same-named fns across modules. The semantically-correct mirror of +lib.rs:1135-1139 is per-module, not the workspace-wide pattern +5c5180f used for types/ctors (which are workspace-unique). + +**Commits:** + +- `3b0bcf3` — `test: red for mono-pass unknown identifier on recursive fn in class workspace` + - RED test: `crates/ail/tests/mono_recursive_fn.rs::mono_pass_handles_recursive_fn_in_class_workspace` + - Fixture: `examples/test_mono_recursive_fn_bug.ail.json` +- `13b36cc` — `fix: mono pass seeds env.globals for recursive top-level fn in class workspace` + +**Verification:** RED test passes, full workspace tests green, +all three bench gates 0 regressed (`bench/check.py`, +`bench/compile_check.py`, `bench/cross_lang.py`). + +**Carried debt (untouched per Iron Law):** + +- Drift-risk comment in `build_workspace_env` says "If `synth` + starts reading a new `Env` field, update both paths" — accurate + but `env.globals` is now seeded in two further places (the + `collect_*` fns themselves) which the comment doesn't mention. + Cosmetic; left alone for the next consolidation pass. +- The four lib.rs gap-related sites flagged in 22-tidy + (`lib.rs:1266 / 1853-1856 / 1978 / 2314-2316`) and the + primitive-name-set consolidation remain queued. This bug + proved one of the env-seeding "gaps" from 22-tidy was + load-bearing, not defensive — a future iter that audits all + four flagged sites is worth its cost.