diff options
author | metagn <metagngn@gmail.com> | 2024-04-09 15:37:34 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-09 14:37:34 +0200 |
commit | 73b0b0d31c156392c64b8b088402695c7e27f0f0 (patch) | |
tree | 21565506254945626654bbf46de46fffe4bd4f52 /compiler | |
parent | c23d6a3cb92a7f4d4a96691148359b917c55d2af (diff) | |
download | Nim-73b0b0d31c156392c64b8b088402695c7e27f0f0.tar.gz |
stop gensym identifiers hijacking routine decl names in templates (#23392)
fixes #23326 In a routine declaration node in a template, if the routine is marked as `gensym`, the compiler adds it as a new symbol to a preliminary scope of the template. If it's not marked as gensym, then it searches the preliminary scope of the template for the name of the routine, then when it matches a template parameter or a gensym identifier, the compiler replaces the name node with a symbol node of the found symbol. This makes sense for the template parameter since it has to be replaced later, but not really for the gensym identifier, as it doesn't allow us to inject a routine with the same name as an identifier previously declared as gensym (the problem in #23326 is when this is in another `when` branch). However this is the only channel to reuse a gensym symbol in a declaration, so maybe removing it has side effects. For example if we have: ```nim proc foo(x: int) {.gensym.} = discard proc foo(x: float) {.gensym.} = discard ``` it will not behave the same as ```nim proc foo(x: int) {.gensym.} = discard proc foo(x: float) = discard ``` behaved previously, which maybe allowed overloading over the gensym'd symbols. A note to the "undeclared identifier" error message has also been added for a potential error code that implicitly depended on the old behavior might give, namely ``undeclared identifier: 'abc`gensym123'``, which happens when in a template an identifier is first declared gensym in code that doesn't compile, then as a routine which injects by default, then the identifier is used.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/lookups.nim | 6 | ||||
-rw-r--r-- | compiler/semtempl.nim | 2 |
2 files changed, 6 insertions, 2 deletions
diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 52296644d..54eb9741f 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -584,7 +584,11 @@ proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extr if name == "_": err = "the special identifier '_' is ignored in declarations and cannot be used" else: - err = "undeclared identifier: '" & name & "'" & extra + err = "undeclared identifier: '" & name & "'" + if "`gensym" in name: + err.add "; if declared in a template, this identifier may be inconsistently marked inject or gensym" + if extra.len != 0: + err.add extra if c.recursiveDep.len > 0: err.add "\nThis might be caused by a recursive module dependency:\n" err.add c.recursiveDep diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 10440614d..be1d3e51f 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -261,7 +261,7 @@ proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode = if n.kind == nkIdent: let s = qualifiedLookUp(c.c, n, {}) if s != nil: - if s.owner == c.owner and (s.kind == skParam or sfGenSym in s.flags): + if s.owner == c.owner and s.kind == skParam: incl(s.flags, sfUsed) result = newSymNode(s, n.info) onUse(n.info, s) |