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

symbol declared in template is considered undeclared if symbol with same name is injected into proc in same template #14620

Open
jibal opened this issue Jun 9, 2020 · 4 comments

Comments

@jibal
Copy link

jibal commented Jun 9, 2020

nim 1.2 on Windows 10

Error message:

x.nim(9, 1) template/generic instantiation of t from here
x.nim(7, 9) Error: undeclared identifier: 'x' [line is bod(x)]

from this code:

template t(body: untyped) =
  proc bod(a: int) =
    let x {.inject.} = a
    body
  
  let x = 1
  bod(x)

t:
  echo x

x is of course declared, contrary to the error message. The injected x is local to proc bod, and even if one of these x "overrides" the other (which makes no sense), the error message makes no sense -- there appears to be some sort of mishandling of the symbol table within the template. There's no error if the argument to bod doesn't reference x, or if the let is moved outside of the template, e.g.,

template t(body: untyped) =
  proc bod(a: int) =
    let x {.inject.} = a
    body
  
  bod(x)

let x = 1
t:
  echo x

This also works fine, as the two xs are not in the same template:

template z(body: untyped) =
  proc bod(a: int) =
    let x {.inject.} = a
    body

template t(body: untyped) =
  z(body)

  let x = 1
  bod(x)

t:
  echo x
@jibal
Copy link
Author

jibal commented Jun 10, 2020

Here's a further minimized failing example:

x.nim(8, 1) Error: undeclared identifier: 'x'
(This is the line invoking the template, unlike the other example where the error occurred at the point of use of x. Presumably this is because x isn't actually used inside the template; change line 6 from "x" to "x+1" and the error occurs there, as before.)

template t =
  proc p =
    let x {.inject.} = 1

  let x = 1
  x

t

Apparently, any use of a variable declared within the template with the same name as a symbol injected into the proc fails because the compiler erroneously thinks the symbol isn't declared.

@jibal jibal changed the title within template, declared symbol is marked undeclared when passed to proc (in same template) that declares injected symbol with same name symbol declared in template is considered undeclared if symbol with same name is injected into proc in same template Jun 10, 2020
@ghost
Copy link

ghost commented Jun 10, 2020

Seems like a duplicate or really similar to #10609

@jibal
Copy link
Author

jibal commented Jun 10, 2020 via email

@jibal
Copy link
Author

jibal commented Jun 10, 2020

Here's an example that illustrates what's happening:

template t(body: untyped) =
  proc p =
    let x {.inject.} = 0

  let x = 1
  body
  echo x

t:
  let x = 2

This prints 2 rather than 1 because x in echo x uses the raw name rather than the gensymed name. This is a lot nastier than the examples that get errors ... you think your template is hygienic but it's not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant