summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-12-27 18:43:56 +0300
committerEugene Burmako <xeno.by@gmail.com>2013-12-27 18:45:10 +0300
commitbbd03b26f1eeba5abf495f5e745c6623f0cc05b7 (patch)
treed988476af3851a7e682f853c4058fe77e4fb4564
parent9f0594c57716ed551918e15be6da843982e8ba12 (diff)
downloadscala-bbd03b26f1eeba5abf495f5e745c6623f0cc05b7.tar.gz
scala-bbd03b26f1eeba5abf495f5e745c6623f0cc05b7.tar.bz2
scala-bbd03b26f1eeba5abf495f5e745c6623f0cc05b7.zip
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.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--test/files/run/t7777.check7
-rw-r--r--test/files/run/t7777/Macros_1.scala17
-rw-r--r--test/files/run/t7777/Test_2.scala6
5 files changed, 40 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
index 54c665fe56..86bf846f1c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
+++ b/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.
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 5e89440bc0..7ff9e854b1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/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
diff --git a/test/files/run/t7777.check b/test/files/run/t7777.check
new file mode 100644
index 0000000000..162ff2d2a2
--- /dev/null
+++ b/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)
diff --git a/test/files/run/t7777/Macros_1.scala b/test/files/run/t7777/Macros_1.scala
new file mode 100644
index 0000000000..459ab3edbb
--- /dev/null
+++ b/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}")
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7777/Test_2.scala b/test/files/run/t7777/Test_2.scala
new file mode 100644
index 0000000000..1fe8b63bab
--- /dev/null
+++ b/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!
+} \ No newline at end of file