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

ProcDef is not re-evaluated between typed macros which was added to the proc pragmas by an another typed macro #18349

Open
alaviss opened this issue Jun 25, 2021 · 1 comment
Labels
CPS bugs/pulls related to the cps project Macros

Comments

@alaviss
Copy link
Collaborator

alaviss commented Jun 25, 2021

Example

import macros

macro foo(x: static[int], n: typed): untyped =
  result = n
  if result.kind in RoutineNodes:
    echo "foo on ", result.name, ", x: ", x
  else:
    echo "foo on ", result.kind, ", x: ", x

macro addFooToBody(x: static[int], n: typed): untyped =
  result = copyNimTree n
  result.body = newStmtList:
    newCall(bindSym"foo", newLit x):
      result.body
  echo "added foo(", x, ") to body"

macro addFoo(n: typed): untyped =
  result = copyNimTree n
  # This is also the wrong order to add the macros, see nim-lang/Nim#18348
  result.addPragma:
    nnkExprColonExpr.newTree(bindSym"addFooToBody", newLit 1)
  result.addPragma:
    nnkExprColonExpr.newTree(bindSym"foo", newLit 2)
 
proc test() {.used, addFoo.} =
  discard

Current Output

added foo(1) to body
foo on test, x: 2
foo on nnkDiscardStmt, x: 1

Expected Output

added foo(1) to body
foo on nnkDiscardStmt, x: 1
foo on test, x: 2

Additional Information

$ nim -v
Nim Compiler Version 1.5.1 [Linux: amd64]
Compiled at 2021-06-24
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: 0f91b67f5c15328330f74a8769aed9961940aab2
active boot switches: -d:release -d:nimUseLinenoise
@alaviss alaviss added Macros CPS bugs/pulls related to the cps project labels Jun 25, 2021
alaviss added a commit to alaviss/cps that referenced this issue Jun 27, 2021
nim-lang/Nim#18349 shows that pragmas
calls are unreliable and bugs might make it way through a phase,
which makes it hard for us to debug
disruptek pushed a commit to nim-works/cps that referenced this issue Jun 27, 2021
nim-lang/Nim#18349 shows that pragmas
calls are unreliable and bugs might make it way through a phase,
which makes it hard for us to debug
@metagn
Copy link
Collaborator

metagn commented Sep 27, 2024

Somewhat simplified:

import macros

macro c(n: typed): untyped =
  result = n
  echo "c"
  echo result.repr

macro b(n: typed): untyped =
  result = copyNimTree n
  result.body = newStmtList(ident"abc") # this is supposed to error
  echo "b"
  echo result.repr

macro a(n: typed): untyped =
  result = copyNimTree n
  result.addPragma(bindSym"b")
  result.addPragma(bindSym"c")
  echo "a"
  echo result.repr
 
proc test() {.a.} =
  discard
a
proc test() {.b, c.} =
  discard

b
proc test() {.c.} =
  abc

c
proc test() =
  abc

a.nim(24, 15) template/generic instantiation of `a` from here
a.nim(18, 12) template/generic instantiation of `b` from here
a.nim(20, 12) template/generic instantiation of `c` from here
a.nim(10, 34) Error: undeclared identifier: 'abc'

My guess is when c is getting called, the proc test() = abc argument is considered typed since it has type tyVoid, and so not rechecked by prepareOperand. Using calls instead of pragmas works, because the next macro receives a different node than the proc node, a call node, always having a nil type.

We can fix this case (checking for formal.kind == tyTyped and a.typ.kind == tyVoid in prepareOperand as well as a.typ == nil), but I don't know about the general case, when the typed argument has non-void type. We could automatically set the type to nil for every macro output with type untyped, but this could break stuff, and there's the question of it being applied recursively. Another option is maybe exposing something like eraseType(node) which sets the type of the node to nil. but maybe this makes users depend on an implementation detail.

There's also the question of "should prepareOperand check for nil type at all", when it could just sem everything given to it. I don't know if this is feasible but as seen in #16867 other things like nkHiddenCallConv have similar problems.

This is effectively the same issue as #18348.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CPS bugs/pulls related to the cps project Macros
Projects
None yet
Development

No branches or pull requests

2 participants