Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding .gensym. to a template does not make it local #2465

Closed
winksaville opened this issue Apr 4, 2015 · 7 comments · Fixed by #22564
Closed

Adding .gensym. to a template does not make it local #2465

winksaville opened this issue Apr 4, 2015 · 7 comments · Fixed by #22564

Comments

@winksaville
Copy link
Contributor

template t() =
  template declX(str: string) {.gensym.} =
    var x {.inject.} : string = str

t()
declX("a string")
echo "x=", x

When compiling:

$ nim c -r --hints:off t
CC: t
[Linking]
/home/wink/prgs/nim/template/t
x=a string
@reactormonk
Copy link
Contributor

From the manual:

Whether a symbol that is declared in a template is exposed to the instantiation scope is controlled by the inject and gensym pragmas: gensym'ed symbols are not exposed but inject'ed are.

so it does exactly what you tell it to.

template t() =
  template declX(str: string) {.gensym.} =
    var x: string = str

t()
declX("a string")
echo "x=", x

Results in

test.nim(7, 11) Error: undeclared identifier: 'x'

as expected.

@Perelandric
Copy link
Contributor

@reactormonk

I was wondering about this bug. I didn't think it was one at first, but I saw that Araq called it a bug in this forum comment.

Looking at it again, shouldn't the gensym pragma make the declX template local to the t template? Seems like it should produce: undeclared identifier: declX. That's what it does with a proc anyway.

template t() =
  proc declX(str: string) {.gensym.} =
    var x: string = str

t()
declX("a string")
echo "x=", x

test.nim(6, 0) Error: undeclared identifier: 'declX'

@reactormonk reactormonk reopened this Apr 5, 2015
@winksaville
Copy link
Contributor Author

In case you didn't realize, the reason you're getting:

test.nim(7, 11) Error: undeclared identifier: 'x'

Is because in your example you didn't have {.inject.} on the x:

var x {.inject.} : string = str

My full example is repeated here with the compile & run output:

$ cat t.nim; nim c -r --hints:off t.nim
template t() =
  template declX(str: string) {.gensym.} =
    var x {.inject.} : string = str

t()
declX("a string")
echo "x=", x
[Linking]
/home/wink/prgs/nim/template/t 
x=a string

As @goob said I would expect this to generate a compile error saying "declX" is undeclared. Instead it works.

@dom96
Copy link
Contributor

dom96 commented Apr 5, 2015

The {.inject.} pragma has nothing to do with this bug. The following should also result in a compile-time error:

template t() =
  template foo() {.gensym.} =
    echo 42

t()
foo()

@timotheecour
Copy link
Member

timotheecour commented Jul 13, 2019

was about to file a new bug (which I ran into while working on #11722) but I found this, looks like the same or similar:
this compiles, but shouldn't

import std/macros

macro mgen(): untyped =
  let name1 = genSym(nskTemplate, "mypriv1")
  let name2 = genSym(nskProc, "mypriv2")
  let name3 = genSym(nskLet, "mypriv3")
  result = newStmtList()
  result.add quote do:
    template `name1`() = echo "in template"
    proc `name2`() = echo "in proc"
    proc bobah() = echo "in bobah"
    let `name3` = 123
  echo repr(result)
  return result

mgen()

bobah() # ok, works
mypriv1()  # BUG: this shouldn't compile, it's genSym'd

when false:
  mypriv2() # inconsistent with mypriv1: this one doesn't compile
  echo mypriv3 # ditto
  mypriv1421054() # the gensym'd name doesn't compile either
  mypriv2421053() # ditto for mypriv2

note

this could affect all code with genSym(nskTemplate, ...

workaround

here's the workaround I found that seems to work: use a name with an underscore, making it impossible to clash:

let name = genSym(nskTemplate, "_fun")

timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 13, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 14, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 15, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 26, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 30, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Aug 23, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Aug 25, 2019
timotheecour added a commit to timotheecour/Nim that referenced this issue Jan 23, 2020
@timotheecour
Copy link
Member

timotheecour commented Jun 12, 2020

the bug in top post is now fixed (as of 6aa971d 1.3.5 at least) but the bug in #2465 (comment) is still here

maybe a simple hacky fix would be to force gensym idents to start with _, although that still may not work eg if mgen is called twice, would those clash? unclear.

timotheecour added a commit to timotheecour/Nim that referenced this issue Mar 20, 2021
timotheecour added a commit to timotheecour/Nim that referenced this issue Mar 20, 2021
timotheecour added a commit to timotheecour/Nim that referenced this issue Mar 22, 2021
timotheecour added a commit to timotheecour/Nim that referenced this issue Apr 2, 2021
Araq pushed a commit that referenced this issue Apr 2, 2021
* new `macros.genAst`: fixes all issues with `quote do`
* add changelog entry
* add workaround for #2465 (comment)
* add test for #9607
* add kNoExposeLocalInjects option
* add test case for nested application of genAst
* genAst: automatically call newLit when needed
* allow skipping `{}`: genAst: foo
* add test that shows this fixes #11986
* add examples showing mixin; add examples showing passing types, macros, templates
* move to std/genasts
* improve docs
@metagn
Copy link
Collaborator

metagn commented Aug 23, 2023

Now:

template t() =
  template foo() {.gensym.} =
    echo 42

t()
foo()

Gives:

(6, 1) Error: undeclared identifier: 'foo'

metagn added a commit to metagn/Nim that referenced this issue Aug 27, 2023
closes nim-lang#12582, closes nim-lang#19552, closes nim-lang#2465, closes nim-lang#4596, closes nim-lang#15246,
closes nim-lang#12683, closes nim-lang#7889, closes nim-lang#4547, closes nim-lang#12415, closes nim-lang#2002,
closes nim-lang#1771, closes nim-lang#5121

The test for nim-lang#5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.
Araq pushed a commit that referenced this issue Aug 27, 2023
* test case haul for old generic/template/macro issues

closes #12582, closes #19552, closes #2465, closes #4596, closes #15246,
closes #12683, closes #7889, closes #4547, closes #12415, closes #2002,
closes #1771, closes #5121

The test for #5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.

* fix template gensym test
narimiran pushed a commit that referenced this issue Sep 18, 2023
* test case haul for old generic/template/macro issues

closes #12582, closes #19552, closes #2465, closes #4596, closes #15246,
closes #12683, closes #7889, closes #4547, closes #12415, closes #2002,
closes #1771, closes #5121

The test for #5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.

* fix template gensym test

(cherry picked from commit c19fd69)
narimiran pushed a commit that referenced this issue Sep 18, 2023
* test case haul for old generic/template/macro issues

closes #12582, closes #19552, closes #2465, closes #4596, closes #15246,
closes #12683, closes #7889, closes #4547, closes #12415, closes #2002,
closes #1771, closes #5121

The test for #5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.

* fix template gensym test

(cherry picked from commit c19fd69)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants