-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Fix macro annotations spliceOwner
#16513
Fix macro annotations spliceOwner
#16513
Conversation
401c956
to
c5050cd
Compare
|
||
quotePickling.println(i"**** unpickled quote\n$tree") | ||
var tree = unpickler.tree |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No var
needed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops
// When a quote is unpickled with a Quotes context that that has a class `spliceOwner` | ||
// we need to use a dummy owner to unpickle it. Otherwise any definitions defined | ||
// in the quoted block would be accidentally entered in the class. | ||
// This owner is replaced with the correct owner when at the splice site. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that in callMacro
? Maybe refer to it explicitly, then it's clearer where the owner gets replaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is in this same file in quotedExprToTree
and quotedTypeToTree
. I added a reference in the comment and explained a bit more.
@@ -31,14 +31,20 @@ trait MacroAnnotation extends StaticAnnotation: | |||
* def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = | |||
* import quotes.reflect._ | |||
* tree match | |||
* case DefDef(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(rhsTree)) => | |||
* (Ref(param.symbol).asExpr, rhsTree.asExpr) match |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are all these macros here and in run-macros changed? Does the old implementation not work anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case, the old implementation still works but is suboptimal and has a bug. It had three issues:
- With quotes getting unpickled in with the wrong owner each splice has the potential to trigger an owner change.
- If users would assemble the expression using reflection they would need extra explicit
changeOwner
calls - To recover the type of the signature we should look at the signature and not the terms. In the previous version, we had an accidental term reference to the parameter of the annotated def that leaked into the new field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative way to construct the RHSs will be added in the documentation in #16454.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make the context changes simpler, I plan to add a method like inContext
.
Something like
val rhs = inQuotes(owner){ '{...} }
c5050cd
to
8d45fcf
Compare
The splice owner of the macro annotation should be the owner of the annotated definition. The issue was that if that owner was a class quotes unpickled with this context accidentally entered definitions in the quotes into the class. Now we unpickle these definitions using a dummy val owner (similar to the LocalDummy).
8d45fcf
to
9431066
Compare
Enable modification of classes with `MacroAnnotation`: * Can annotate `class` to transform it * Can annotate `object` to transform the companion class Supported class modifications: * Modify the implementations of `def`, `val`, `var`, `lazy val`, `class`, `object` in the class * Add new `def`, `val`, `var`, `lazy val`, `class`, `object` members to the class * Add a new override for a `def`, `val`, `var`, `lazy val` members in the class Restrictions: * An annotation on a top-level class cannot return a top-level `def`, `val`, `var`, `lazy val`. Related PRs: * Includes #16513 * Follows #16392 * Followed by #16534
The splice owner of the macro annotation should be the owner of the
annotated definition. The issue was that if that owner was a class
quotes unpickled with this context accidentally entered definitions
in the quotes into the class. Now we unpickle these definitions using
a dummy val owner (similar to the LocalDummy).