Skip to content

Commit

Permalink
gensym anonymous proc symbols (#24422)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
metagn authored Nov 9, 2024
1 parent 8091d76 commit 3e47725
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
1 change: 1 addition & 0 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 41 additions & 0 deletions tests/proc/tanonprocresem.nim
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 3e47725

Please sign in to comment.