-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Defining a closure in a macro causes a compiler exception #12309
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
Comments
I also tried separating the val resultDefSymbol = Symbol.newMethod(Symbol.spliceOwner, "getResult", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[String]))
val resultDef = DefDef(resultDefSymbol, { case _ => Some(resultDefBody()) })
val resultExpr = Closure(Ref(resultDefSymbol), None).asExprOf[() => String]
Block(List(resultDef), '{ TestMacro.use($resultExpr) }.asTerm).asExprOf[Unit] but this causes the same exception ( |
As the signature of the method/closure that I'm trying to create is static, but the body is dynamically generated, a work-around might be to quote the whole definition of the method: val getResultDef: Term = '{
def getResult(): String = {
val result: String = "xxx"
result
}
}.asTerm but then, how to get hold of the |
Compiling this code using the
A simple way to fix the code is to change the owner of the content of - val resultDef = DefDef(resultDefSymbol, { case _ => Some(resultDefBody()) })
+ val resultDef = DefDef(resultDefSymbol, { case _ => Some(resultDefBody().changeOwner(resultDefSymbol)) }) |
To avoid the explicit change of owner we could introduce a way to create a |
Thanks! This solved both problems (in the minimised & original macros). Since |
The issue is that if we make
Yes, that should be mentioned in the documentation of |
I think checking owners is probably not going to add much overhead. You just need to traverse down to all nested definition but not beyond them. It's changing owners which is costly. So I would be in favor of making DefDef and related constructors maintain owners automatically. |
The issue is that if we do it automatically, then users will probably not care about creating the trees with the correct owner. Then the norm would be to have to do an owner change. |
@nicolasstucki is that really a problem? If the owner is changed only once when constructing the thing, as opposed to on every transformation of the tree. It's only a constant cost to pay. Should macro users who just want to quickly put some trees together have to care about owners, something the compiler should in principle be able to figure out on its own? Symbol owners and owner chain corruptions were probably the number one cause for unreliability and crashes with Scala 2 macros. The entire thing was so complicated that it was basically impossible to get it right, from my experience (though at the time I tried to do this I was less experimented). Look at this old tutorial for example. Any deviation from the compiler's internal notion of how things must be done led to horrible crashes. This is one of the main reason people ended up simply wiping types off the trees they received in macros, and just using untyped tree manipulations throughout their macros, which has its own set of problems. |
Uh oh!
There was an error while loading. Please reload this page.
Compiler version
3.0.0-RC3
Minimized example
and then calling the macro:
Output
I'm trying to generate code which passes a function as a parameter to a method. From what I've seen by printing the AST of quoted code, I need a
Block
with aDefDef
as the statement, and aClosure
as the expression. In the body of the function, I define a local variable - and this seems to be a problem. The original exception from the compiler I get is:while trying to minify the example, I started getting another exception, so I'm not sure if my code reproduces the problem, but maybe it reproduces some problem :)
Here's the exception I get now:
When printing the generated code, it looks fine:
Expectation
A way to generate a closure and pass it to a method, in a macro.
The text was updated successfully, but these errors were encountered: