From 3e47725c08b42515d17d77b3a6c9cc3029e5681c Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 9 Nov 2024 14:33:23 +0300 Subject: [PATCH] gensym anonymous proc symbols (#24422) fixes #14067, fixes #15004, fixes #19019 Anonymous procs are [added to scope](https://github.com/nim-lang/Nim/blob/8091d76306c23b866af00d384b9b6f929ef8ed23/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. --- compiler/semstmts.nim | 1 + tests/proc/tanonprocresem.nim | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/proc/tanonprocresem.nim diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 60778d25d687..8061f316df04 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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 diff --git a/tests/proc/tanonprocresem.nim b/tests/proc/tanonprocresem.nim new file mode 100644 index 000000000000..320d01a78291 --- /dev/null +++ b/tests/proc/tanonprocresem.nim @@ -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"