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

result variable is not hygienic in templates #7791

Open
krux02 opened this issue May 7, 2018 · 5 comments
Open

result variable is not hygienic in templates #7791

krux02 opened this issue May 7, 2018 · 5 comments

Comments

@krux02
Copy link
Contributor

krux02 commented May 7, 2018

When a template introduces a new variable, it is normally hidden in the context where the templates expands into, to prevent name clashes. The problem is, that when a template generates a function header, this function has this implicit result variable that is not hidden.

Best seen in this example

template foobar(targ: untyped): untyped =
  ## this template should only put ``arg`` in a context where a result
  ## variable exist.  The variables ``hidden`` I have put here to
  ## create a comparison of how a variables shold behave.
  proc foo(arg: bool): bool =
    result = arg
    # this variable is correctly hidden with the hygenic template.
    let hidden = "mystring"
    targ

  # Well this part of the template is pretty pointless.  I just put it
  # here, so the generated function is actually used.
  if foo(true):
    echo "bar"

  if foo(false):
    echo "bara"

proc bananas(): int =
  result = 123 # <-- should bind to this, but it doesn't ----,
  var hidden = 111 #                                          \
  foobar: #                                                   |
    # this binds correctly to the local variable.             |
    hidden += 123 #                                           |
    # this ``result`` binds to the result:bool defined in the |
    # template.  This violates hygenic macros.                /
    result += 123  # ----------------------------------------´

compilation output:

scratch.nim(20, 3) template/generic instantiation from here
scratch.nim(24, 12) Error: type mismatch: got <bool, int literal(123)>
but expected one of: 
proc `+=`[T: SomeOrdinal | uint | uint64](x: var T; y: T)
  first type mismatch at position: 2
  required type: T: int or int8
  but expression '123' is of type: int literal(123)
proc `+=`[T: float | float32 | float64](x: var T; y: T)
  first type mismatch at position: 1
  required type: var T: float or float32
  but expression 'result' is of type: bool

expression: result += 123

Compilation exited abnormally with code 1 at Mon May  7 13:58:34

This causes a problem in my ast pattern matching library:
krux02/ast-pattern-matching#6

@mratsim
Copy link
Collaborator

mratsim commented May 8, 2018

Maybe related to this: #7323

@krux02
Copy link
Contributor Author

krux02 commented May 12, 2018

@mratsim The cause for the problem you link to is a different one. The quote do notation tries to bind local variables and functions that are in scope, including the result variable, and this basically goes wrong all the time.

@mratsim
Copy link
Collaborator

mratsim commented Aug 21, 2018

Forgot about this when I created #8208, it's not just the result variable, all variables are unhygienic when the template is used inside a proc.

@innerop
Copy link

innerop commented Nov 4, 2018

Wondering, any progress on this?

@krux02
Copy link
Contributor Author

krux02 commented Nov 4, 2018

I just tested it, it is still broken.

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

No branches or pull requests

4 participants