From f48efa4b1f6c0c6c5e55f7ccb5b43185c4a90f86 Mon Sep 17 00:00:00 2001 From: araq Date: Mon, 31 Aug 2026 19:00:48 +0200 Subject: [PATCH] IC: record that the lazy `interfHidden` conversion does not work yet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tried it. The shape is easy and it is not the problem: `modulegraphs` already imports `ast2nif` so no callback hook is needed, every read of `interfHidden` goes through `interfSelect`, and its four call sites all have the graph and the module to hand. It builds, and it keeps privacy — a plain `import` still rejects a private symbol under both `--ic:on` and `--ic:off`. But `import x {.all.}` then fails under `--ic:on` with "undeclared identifier", where it works today and works under `--ic:off`. Silent, and entangled with the driver's discovery loop: the module is not in `DecodeContext.mods` when the lookup asks, on a cold cache and on a warm one alike. Three fixes tried, none of them it, recorded in `bnode.nim` so nobody re-guesses them: clearing `hiddenPending` only on success (necessary, not sufficient — one early miss otherwise costs the module its hidden symbols for the whole process); loading the module inside the lazy builder rather than assuming the caller did; and building into a local `TStrTable` in case the `var` alias into `g.ifaces` was being invalidated by the seq growing underneath it. After all three, `ensureHiddenIface` still reports the module missing on every one of its 19 calls. So the next attempt starts by instrumenting `moduleId`'s FileIndex against `moduleFromNifFile`'s — whatever sets `hiddenPending` and whatever fills `c.mods` are not agreeing about which module they mean — before any more of the mechanism gets written. The 1.05s is still there and still worth having. Comment-only. ic 41/41. --- compiler/bnode.nim | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/compiler/bnode.nim b/compiler/bnode.nim index f8884d51cc..613ac1e8d0 100644 --- a/compiler/bnode.nim +++ b/compiler/bnode.nim @@ -147,8 +147,37 @@ ## the whole Atlas build 22.19s -> 20.47s. Doing it CORRECTLY means populating ## the table lazily on first `interfSelect(true)` rather than deciding ## up front — a macro-generated `{.all.}` import cannot be seen syntactically, -## and guessing wrong loses symbols silently. `loaderCtx` is the hook: the -## module index is still in the DecodeContext after loading. +## and guessing wrong loses symbols silently. +## +## That lazy conversion has been ATTEMPTED and does not work as a +## substitution. The shape is easy: `modulegraphs` already imports `ast2nif` +## (the dependency runs that way, so no callback hook is needed), every read of +## `interfHidden` goes through `interfSelect`, and its 4 call sites all have +## the graph and the module to hand. It builds and it keeps privacy — a plain +## `import` still rejects a private symbol under both `--ic:on` and +## `--ic:off` — but `import x {.all.}` then fails under `--ic:on` with +## "undeclared identifier", where it works today and works under `--ic:off`. +## The failure is silent and it is entangled with the driver's discovery loop: +## the module is not in `DecodeContext.mods` at the point the lookup asks, on +## a COLD cache and on a warm one. +## +## Three fixes were tried and none of them is it, recorded so nobody +## re-guesses them: +## * clearing `hiddenPending` only when the build SUCCEEDS, so an import +## whose `.s.bif` does not exist yet is retried rather than written off. +## Necessary — one early miss otherwise costs the module its hidden +## symbols for the whole process — but not sufficient. +## * loading the module inside the lazy builder (`moduleId` is idempotent) +## instead of assuming the caller already did. +## * building into a LOCAL `TStrTable` and assigning it back, in case the +## `var` alias into `g.ifaces` was being invalidated by the seq growing +## during the load. +## After all three, `ensureHiddenIface` still reports the module missing from +## `DecodeContext.mods` on every one of its 19 calls. Whatever populates +## `hiddenPending` and whatever populates `c.mods` are not agreeing about +## which module they mean, and that is where the next attempt should start — +## with `moduleId`'s FileIndex against `moduleFromNifFile`'s, instrumented at +## both ends, before any more of the mechanism is written. ## * `-d:icBridgeOnly` builds the buffer but generates off the tree, which ## separates the ENCODER's cost from the READER's. Encoding is free — it does ## not show in wall time at all.