Skip to content

Commit

Permalink
make routine implicitly gensym when other gensym symbol exists again
Browse files Browse the repository at this point in the history
fixes nim-lang#23813, partially reverts nim-lang#23392
  • Loading branch information
metagn committed Jul 15, 2024
1 parent 8301533 commit c0262af
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 8 deletions.
12 changes: 7 additions & 5 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -256,25 +256,27 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode =
if not isField:
styleCheckUse(c, n.info, s)

proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
proc semRoutineInTemplName(c: var TemplCtx, n: PNode, explicitInject: bool): PNode =
result = n
if n.kind == nkIdent:
let s = qualifiedLookUp(c.c, n, {})
if s != nil:
if s.owner == c.owner and s.kind == skParam:
if s.owner == c.owner and (s.kind == skParam or
(sfGenSym in s.flags and not explicitInject)):
incl(s.flags, sfUsed)
result = newSymNode(s, n.info)
onUse(n.info, s)
else:
for i in 0..<n.safeLen:
result[i] = semRoutineInTemplName(c, n[i])
result[i] = semRoutineInTemplName(c, n[i], explicitInject)

proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
result = n
checkSonsLen(n, bodyPos + 1, c.c.config)
if n.kind notin nkLambdaKinds:
# routines default to 'inject':
if symBinding(n[pragmasPos]) == spGenSym:
let binding = symBinding(n[pragmasPos])
if binding == spGenSym:
let (ident, hasParam) = getIdentReplaceParams(c, n[namePos])
if not hasParam:
var s = newGenSym(k, ident, c)
Expand All @@ -286,7 +288,7 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
else:
n[namePos] = ident
else:
n[namePos] = semRoutineInTemplName(c, n[namePos])
n[namePos] = semRoutineInTemplName(c, n[namePos], binding == spInject)
# open scope for parameters
openScope(c)
for i in patternPos..paramsPos-1:
Expand Down
9 changes: 6 additions & 3 deletions doc/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -6216,9 +6216,12 @@ scope is controlled by the `inject`:idx: and `gensym`:idx: pragmas:
`gensym`'ed symbols are not exposed but `inject`'ed symbols are.

The default for symbols of entity `type`, `var`, `let` and `const`
is `gensym` and for `proc`, `iterator`, `converter`, `template`,
`macro` is `inject`. However, if the name of the entity is passed as a
template parameter, it is an `inject`'ed symbol:
is `gensym`. For `proc`, `iterator`, `converter`, `template`,
`macro`, the default is `inject`, but if a `gensym` symbol with the same name
is defined in the same syntax-level scope, it will be `gensym` by default.
This can be overriden by marking the routine as `inject`.

If the name of the entity is passed as a template parameter, it is an `inject`'ed symbol:

```nim
template withFile(f, fn, mode: untyped, actions: untyped): untyped =
Expand Down
12 changes: 12 additions & 0 deletions tests/template/tinnerouterproc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ block: # #20002
discard 3.bar # evaluates to 10 but only check if it compiles for now
block:
foo()

block: # issue #23813
template r(body: untyped) =
proc x() {.gensym.} =
body
template g() =
r:
let y = 0
r:
proc y() = discard
y()
g()

0 comments on commit c0262af

Please sign in to comment.