Skip to content

fixes #26457; nimsuggest: VM runs stale compile-time procs after a module is recompiled - #26463

Open
Araq wants to merge 2 commits into
develfrom
fix-26457
Open

Araq wants to merge 2 commits into
develfrom
fix-26457

Conversation

@Araq

@Araq Araq commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

fixes #26457

When nimsuggest recompiles a dirty module, the module's IdGenerator restarted from scratch, so its new symbols and types got the same ItemIds as the previous compilation's. But the old ones can still be alive: the VM caches compiled procs, proc handles, globals, consts and layouts by ItemId, and generic instances and lifted hooks minted with the module's ids are cached by other modules (the generic's owner). After an edit, these collided with new symbols. For example, let f = p1; f() ran a different proc, and you got "VM produced a value that refers to invalid memory", "constant expression expected" and similar errors, and nimsuggest stopped answering.

Now the module's id generator is stored in its Iface (moduleIdgen), and a recompilation continues where the last one stopped, so ids are never reused. A full recompile (resetAllModules) still starts fresh. The first commit of this PR invalidated the VM caches instead; that missed the instance/hook caches (see the review comment), so it was replaced.

Tests:

  • nimsuggest/tests/t26457.nim: the issue's example
  • nimsuggest/tests/tlifted_hook_inst.nim: the reproduction from the review (generic instance and lifted =destroy cached by the fixture)

Both fail on devel and pass now. The nimsuggest suite and the ic and vm test categories pass.

🤖 Generated with Claude Code

…dule is recompiled

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nitely

nitely commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

This fixes the reported issue, but nimlangserver then fails in a different place (than devel). You can reproduce the "new" nimlangserver.nim (commit b5050c5) issue like this:

nimsuggest --v4 --stdin nimlangserver.nim 2>&1 | tee ./ns_out.txt
(wait for the prompt to finish before editing; then add `discard 1` after debug line in main proc)
changed nimlangserver.nim
chk nimlangserver.nim
def nimlangserver.nim:164:6

./ns_out.txt contains among many hints:

chk  skUnknown    Error  ../json_serialization/reader_impl.nim	188	20	"attempt to free memory that was not allocated 0 in region kind none"
chk  skUnknown    Error  ../json_serialization/reader_impl.nim	192	50	"expression \'\' has no type (or is ambiguous)"	0
chk  skUnknown    Error  ../json_serialization/reader_impl.nim	192	50	"illformed AST: "	0
def  (empty)

I think #26381 may contain other reproductions as I went down a similar path.

@nitely

nitely commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Possible reproduction:

nimsuggest/tests/fixtures/mlifted_hook_inst.nim

type Box*[T] = object
  name: string
  val*: T

proc box*[T](v: T): Box[T] = Box[T](name: "box", val: v)

nimsuggest/tests/tlifted_hook_inst.nim

import fixtures/mlifted_hook_inst

proc useBox(): int {.compileTime.} =
  let b = box(1)
  b.val
const c0 = useBox()

proc p1(): string {.compileTime.} = "s1"
const c1 = (let f = p1; f())

proc foo*(): int = 1

# `box[int]` and the `=destroy` lifted for `Box[int]` are minted with this
# module's ids, but are cached under the generics of the fixture, so a
# recompilation of this module reuses them while `p1` gets the id the hook
# had. The VM must not hand `p1` the hook's proc handle (or the other way
# around): calling `f` then runs `=destroy`.
discard """
$nimsuggest --tester --v4 $file
>chk $file
chk;;skUnknown;;;;Hint;;$file;;6;;6;;"\'c0\' is declared but not used [XDeclaredButNotUsed]";;0
>changed $file
>chk $file
chk;;skUnknown;;;;Hint;;$file;;6;;6;;"\'c0\' is declared but not used [XDeclaredButNotUsed]";;0
chk;;skUnknown;;;;Hint;;$file;;9;;6;;"\'c1\' is declared but not used [XDeclaredButNotUsed]";;0
"""

gives:

  Expected:
chk     skUnknown               Hint    /home/esteban/AtomProjects/nim-Nim/nimsuggest/tests/tlifted_hook_inst.nim      6       6       "\'c0\' is declared but not used [XDeclaredButNotUsed]"0
chk     skUnknown               Hint    /home/esteban/AtomProjects/nim-Nim/nimsuggest/tests/tlifted_hook_inst.nim      9       6       "\'c1\' is declared but not used [XDeclaredButNotUsed]"0

  But got:
chk     skUnknown               Error   /home/esteban/AtomProjects/nim-Nim/nimsuggest/tests/tlifted_hook_inst.nim      9       11      "constant expression expected"  0
[...]

If it's like in #26381 we'll keep finding these, though. I gave up on #26381 after finding more issues that are not fixed in that branch.

Symbols and types of a module's previous compilation can still be alive
(generic instances and lifted hooks cached by other modules, the VM's
caches), so the module's IdGenerator now resumes where it stopped instead
of restarting. This replaces the VM cache invalidation of the previous
commit, which missed these other stale references.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nimsuggest: after an edit, the VM runs the wrong compile-time proc; regression in devel

2 participants