gensym anonymous proc symbols (#24422)

fixes #14067, fixes #15004, fixes #19019

Anonymous procs are [added to
scope](8091d76306/compiler/semstmts.nim (L2466))
with the name `:anonymous`. This means that if they have the same
signature in a scope, they can consider each other as redefinitions. To
prevent this, mark their symbols as `sfGenSym` so they do not get added
to scope or cause any name conflicts. The commented out `and not isAnon`
check wouldn't work because `isAnon` would not be true if the proc is
being resemmed, in which case the name field in the proc AST would have
the symbol of the anonymous proc rather than being empty.

There is a separate problem of default values in generic/normal procs
not opening new scopes which is partially responsible for #19019.

(cherry picked from commit 3e47725c08)
This commit is contained in:
metagn
2024-11-09 14:33:23 +03:00
committed by narimiran
parent f292393816
commit 3642f4d375
2 changed files with 42 additions and 0 deletions

View File

@@ -2359,6 +2359,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
of nkEmpty:
s = newSym(kind, c.cache.idAnon, c.idgen, c.getCurrOwner, n.info)
s.flags.incl sfUsed
s.flags.incl sfGenSym
n[namePos] = newSymNode(s)
of nkSym:
s = n[namePos].sym

View File

@@ -0,0 +1,41 @@
block: # issue #19019
proc start(draw:proc=(proc()=echo "default"), init:proc=(proc()=echo "default"), reshape:proc=(proc()=echo "default"))=discard
start()
block: # issue #14067
type
Result[T, E] = object
DataProc = proc(val: openArray[byte])
GetProc = proc (onData: DataProc): Result[bool, cstring]
func get[T, E](self: Result[T, E]): T =
discard
template `[]`[T, E](self: Result[T, E]): T =
self.get()
proc testKVStore() =
var v: seq[byte]
var p: GetProc
discard p(proc(data: openArray[byte]) =
v = @data
)[]
if false: testKVStore()
import std/macros
block: # issue #15004
macro fn(fun:untyped):untyped =
newTree(nnkTupleConstr, newLit"first", fun)
macro fn(key:string, fun:untyped):untyped =
newTree(nnkTupleConstr, newLit"second", fun)
let c = fn(proc(count:int):string =
return "x = " & $count
)
doAssert c[0] == "first"
doAssert c[1](123) == "x = 123"