IC: progress

This commit is contained in:
Araq
2026-06-22 13:39:09 +02:00
parent 46b0555326
commit cdb901e174
3 changed files with 25 additions and 1 deletions

View File

@@ -157,6 +157,14 @@ proc ownsRuntimeRoutine(s: PSym; modPos: int): bool =
## - generic instances (`sfFromGeneric`): emitted by demand, deduped by merge;
## - `importc`/`compileTime`/`error`/forward sentinels and meta signatures:
## not real codegen targets.
## - method DISPATCHERS (`sfDispatcher`): their bodies are (re)synthesized into
## the main TU by `emitMethodDispatchers`/`generateIfMethodDispatchers`, never
## per module. A dispatcher is a `copySym` clone of the method that shares the
## method's body sub-tree (incl. its closure iterator); transforming it here
## would lambda-lift that SHARED iterator a SECOND time under a different owner
## identity, baking a conflicting `up` field → "up references do not agree"
## (the divergence is impossible in non-IC, where the dispatcher body is empty
## at lift time). So a dispatcher is never an owned runtime routine.
## A `{.closure.}` iterator IS a standalone runtime routine (unlike an inline
## iterator, which is expanded at each call site) and must be emitted by its
## owner — else a cross-module `for` over it links to nothing.
@@ -166,6 +174,7 @@ proc ownsRuntimeRoutine(s: PSym; modPos: int): bool =
s.skipGenericOwner != nil and s.skipGenericOwner.kind == skModule and
s.magic == mNone and
sfFromGeneric notin s.flags and
sfDispatcher notin s.flags and
{sfForward, sfImportc, sfCompileTime, sfError} * s.flags == {} and
s.typ != nil and not signatureHasMetaType(s.typ) and
s.ast != nil and s.ast.safeLen > bodyPos and

View File

@@ -619,7 +619,7 @@ proc runIcTestFile(inp: string) =
const icSuite = ["thallo", "tconverter", "timp", "tmiscs", "tparseutils",
"tcompiletimeglobal", "tsighashstable", "tpureenum", "tgenericoffer",
"tconverterreexport", "ttypeoffer", "ttransitiveoffer",
"tmodsymref"]
"tmodsymref", "tmethupref"]
proc icTest(args: string) =
temp("")

15
tests/ic/tmethupref.nim Normal file
View File

@@ -0,0 +1,15 @@
discard """
output: '''42'''
"""
# Regression test: a `{.base.}` method whose body holds a closure iterator with a
# nested capturing closure must not crash the IC backend. The method's dispatcher
# (a `copySym` clone sharing the iterator) must NOT be lambda-lifted per module;
# otherwise the shared iterator's `up` field is baked twice under divergent owner
# identities -> "up references do not agree" / "could not determine closure type"
# (the real-world symptom: ~all libp2p async `{.base.}` methods failed under
# `nim ic`). Fixed by excluding `sfDispatcher` from nifbackend.ownsRuntimeRoutine.
import mmethupref
let b = Base(val: 40)
echo b.compute()