Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

SI-7777 applyDynamic macro fails for nested application

Interplay between the insertApply desugaring and the invokeDynamic desugarings
is already quite brittle, but the real fun begins when macros crash the party.

The proposed patch enriches the `isDesugaredApply` check performed in
`mkInvoke`, the invokeDynamic desugarer, and makes sure that everything
is safe and sound in the macroland.
  • Loading branch information...
commit bbd03b26f1eeba5abf495f5e745c6623f0cc05b7 1 parent 9f0594c
@xeno-by xeno-by authored
View
4 src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
@@ -50,6 +50,10 @@ trait StdAttachments {
case _ => false
}
+ /** Returns the original tree of the macro expansion if the argument is a macro expansion or EmptyTree otherwise.
+ */
+ def macroExpandee(tree: Tree): Tree = tree.attachments.get[MacroExpansionAttachment].map(_.expandee).getOrElse(EmptyTree)
+
/** After macro expansion is completed, links the expandee and the expansion result by annotating them both with a `MacroExpansionAttachment`.
* The `expanded` parameter is of type `Any`, because macros can expand both into trees and into annotations.
*/
View
9 src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3953,9 +3953,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = {
debuglog(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)")
val treeInfo.Applied(treeSelection, _, _) = tree
- def isDesugaredApply = treeSelection match {
- case Select(`qual`, nme.apply) => true
- case _ => false
+ def isDesugaredApply = {
+ val protoQual = macroExpandee(qual) orElse qual
+ treeSelection match {
+ case Select(`protoQual`, nme.apply) => true
+ case _ => false
+ }
}
acceptsApplyDynamicWithType(qual, name) map { tp =>
// If tp == NoType, pass only explicit type arguments to applyXXX. Not used at all
View
7 test/files/run/t7777.check
@@ -0,0 +1,7 @@
+foo(1, 2)
+bar(4, 5)
+foo(3)
+bar(7)
+apply(6)
+apply(9)
+foo(8)
View
17 test/files/run/t7777/Macros_1.scala
@@ -0,0 +1,17 @@
+import scala.language.experimental.macros
+import scala.language.dynamics
+import scala.reflect.macros.WhiteboxContext
+
+class DynMacro extends Dynamic {
+ def applyDynamic(s: String)(xs: Any*): DynMacro =
+ macro DynMacro.applyDynamicMacro
+}
+
+object DynMacro extends DynMacro {
+ def applyDynamicMacro(c: WhiteboxContext)(s: c.Expr[String])(xs: c.Expr[Any]*): c.Expr[DynMacro] = {
+ import c.universe._
+ val Literal(Constant(n: String)) = s.tree
+ val args = xs.map(_.tree.toString).mkString("(", ", ", ")")
+ c.Expr(q"println(${ n + args }); ${c.prefix.tree}")
+ }
+}
View
6 test/files/run/t7777/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ DynMacro.foo(1, 2) // prints "foo(1, 2)"
+ DynMacro.foo(3).bar(4, 5) // prints "bar(4, 5)", then "foo(3)"
+ DynMacro(6).bar(7) // prints "bar(7)", then "apply(6)"
+ DynMacro.foo(8)(9) // Fails!
+}
Please sign in to comment.
Something went wrong with that request. Please try again.