IC: bugfix (#25982)

This commit is contained in:
Andreas Rumpf
2026-07-10 14:07:35 +02:00
committed by GitHub
parent 4b1444e728
commit fa66510f7a
4 changed files with 57 additions and 1 deletions

View File

@@ -288,6 +288,14 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
result = copySym(result)
result.ast = n.sym.ast
put(c.p, n.sym, result)
if result.state == Sealed:
# the symbol was loaded from another module's NIF cache (e.g. a param
# symbol spliced out of an imported proc type by a `typed` macro) and is
# therefore immutable; the caller re-owns it and assigns its type/flags,
# so hand back a fresh, mutable copy owned by the current module instead.
let fresh = copySym(result, c.idgen)
fresh.ast = result.ast
result = fresh
# when there is a nested proc inside a template, semtmpl
# will assign a wrong owner during the first pass over the
# template; we must fix it here: see #909

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", "tmethupref", "temit"]
"tmodsymref", "tmethupref", "temit", "ttraitparam"]
proc icTest(args: string) =
temp("")

34
tests/ic/mtraitparam.nim Normal file
View File

@@ -0,0 +1,34 @@
import std/macros
type
Chunk* = ref object
x*: int32
ChunkTrait* = distinct tuple[
loaded: proc(self: pointer, chunk: Chunk)
]
macro makeVTable*(traitType: typedesc): untyped =
## Splice the param symbols out of an imported proc type into a fresh proc
## type nested in a fresh tuple type. Under `nim ic` the imported trait is
## loaded from a NIF cache, so its param symbols are `Sealed`; re-owning them
## in `semProcTypeNode` used to trip `ast.nim` `s.state != Sealed`.
var t = traitType.getTypeInst[1].getTypeImpl
if t.kind == nnkDistinctTy: t = t[0]
let formalParams = t[0][1][0]
var bridgeParams = nnkFormalParams.newTree(formalParams[0].copyNimTree)
bridgeParams.add nnkIdentDefs.newTree(ident"p", ident"pointer", newEmptyNode())
for j in 2 ..< formalParams.len:
bridgeParams.add formalParams[j].copyNimTree
let vtType = nnkTupleTy.newTree(
nnkIdentDefs.newTree(ident"m0",
nnkProcTy.newTree(bridgeParams, nnkPragma.newTree(ident"nimcall")),
newEmptyNode()))
let vtName = genSym(nskType, "VT")
let vtVar = genSym(nskVar, "vt")
result = nnkStmtList.newTree(
nnkTypeSection.newTree(
nnkTypeDef.newTree(vtName, newEmptyNode(), vtType)),
nnkVarSection.newTree(
nnkIdentDefs.newTree(
nnkPragmaExpr.newTree(vtVar, nnkPragma.newTree(ident"used")),
vtName, newEmptyNode())))

14
tests/ic/ttraitparam.nim Normal file
View File

@@ -0,0 +1,14 @@
discard """
output: '''ok'''
"""
# Regression test: a `typed` macro in an imported module splices param symbols
# out of an imported proc type into a freshly semchecked proc type. Under
# `nim ic` those param symbols are loaded `Sealed` from the NIF cache; reusing
# them in `newSymG`/`semProcTypeNode` used to fail `ast.nim` `s.state != Sealed`.
import mtraitparam
makeVTable(ChunkTrait)
echo "ok"