summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-12-27 22:29:54 +0300
committerEugene Burmako <xeno.by@gmail.com>2013-12-28 21:05:13 +0300
commitd92effc8a995086c1e0c4482f6163ef17b289ede (patch)
treefee3ba6e309abe1b6c488d62721b3ce991c5bc2e
parentbbd03b26f1eeba5abf495f5e745c6623f0cc05b7 (diff)
downloadscala-d92effc8a995086c1e0c4482f6163ef17b289ede.tar.gz
scala-d92effc8a995086c1e0c4482f6163ef17b289ede.tar.bz2
scala-d92effc8a995086c1e0c4482f6163ef17b289ede.zip
SI-8006 prevents infinite applyDynamicNamed desugarings
Since mkInvoke, the applyDynamic/selectDynamic/etc desugarer, is disconnected from typedNamedApply, the applyDynamicNamed argument rewriter, the latter doesn’t know whether it needs to apply the rewriting because the application has just been desugared or it needs to hold on because it’s already performed a desugaring on this tree. This commit introduces the attachment that links these translation facilities, preventing infinite applyDynamicNamed desugarings.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
-rw-r--r--test/files/neg/t6920.check6
-rw-r--r--test/files/neg/t6920.scala10
-rw-r--r--test/files/neg/t8006.check6
-rw-r--r--test/files/neg/t8006.scala8
6 files changed, 47 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
index 86bf846f1c..14f47a00fd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
@@ -151,4 +151,18 @@ trait StdAttachments {
* because someone has put MacroImplRefAttachment on it.
*/
def isMacroImplRef(tree: Tree): Boolean = tree.attachments.get[MacroImplRefAttachment.type].isDefined
+
+ /** Since mkInvoke, the applyDynamic/selectDynamic/etc desugarer, is disconnected
+ * from typedNamedApply, the applyDynamicNamed argument rewriter, the latter
+ * doesn’t know whether it needs to apply the rewriting because the application
+ * has just been desugared or it needs to hold on because it’s already performed
+ * a desugaring on this tree. This has led to SI-8006.
+ *
+ * This attachment solves the problem by providing a means of communication
+ * between the two Dynamic desugarers, which solves the aforementioned issue.
+ */
+ case object DynamicRewriteAttachment
+ def markDynamicRewrite(tree: Tree): Tree = tree.updateAttachment(DynamicRewriteAttachment)
+ def unmarkDynamicRewrite(tree: Tree): Tree = tree.removeAttachment[DynamicRewriteAttachment.type]
+ def isDynamicRewrite(tree: Tree): Boolean = tree.attachments.get[DynamicRewriteAttachment.type].isDefined
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 7ff9e854b1..910da77ca8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3369,7 +3369,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
(args exists isNamedArg) || // uses a named argument
isNamedApplyBlock(fun)) { // fun was transformed to a named apply block =>
// integrate this application into the block
- if (dyna.isApplyDynamicNamed(fun)) dyna.typedNamedApply(tree, fun, args, mode, pt)
+ if (dyna.isApplyDynamicNamed(fun) && isDynamicRewrite(fun)) dyna.typedNamedApply(tree, fun, args, mode, pt)
else tryNamesDefaults
} else {
val tparams = context.extractUndetparams()
@@ -3927,7 +3927,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
gen.mkTuple(List(CODE.LIT(""), arg))
}
- val t = treeCopy.Apply(orig, fun, args map argToBinding)
+ val t = treeCopy.Apply(orig, unmarkDynamicRewrite(fun), args map argToBinding)
wrapErrors(t, _.typed(t, mode, pt))
}
@@ -3992,7 +3992,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val nameStringLit = atPos(treeSelection.pos.withStart(treeSelection.pos.point).makeTransparent) {
Literal(Constant(name.decode))
}
- atPos(qual.pos)(Apply(fun, List(nameStringLit)))
+ markDynamicRewrite(atPos(qual.pos)(Apply(fun, List(nameStringLit))))
case _ =>
setError(tree)
}
diff --git a/test/files/neg/t6920.check b/test/files/neg/t6920.check
new file mode 100644
index 0000000000..ee4eafb83e
--- /dev/null
+++ b/test/files/neg/t6920.check
@@ -0,0 +1,6 @@
+t6920.scala:9: error: too many arguments for method applyDynamicNamed: (values: Seq[(String, Any)])String
+error after rewriting to CompilerError.this.test.applyDynamicNamed("crushTheCompiler")(scala.Tuple2("a", 1), scala.Tuple2("b", 2))
+possible cause: maybe a wrong Dynamic method signature?
+ test.crushTheCompiler(a = 1, b = 2)
+ ^
+one error found
diff --git a/test/files/neg/t6920.scala b/test/files/neg/t6920.scala
new file mode 100644
index 0000000000..b79d641698
--- /dev/null
+++ b/test/files/neg/t6920.scala
@@ -0,0 +1,10 @@
+import scala.language.dynamics
+
+class DynTest extends Dynamic {
+ def applyDynamicNamed(name: String)(values: Seq[(String, Any)]) = "test"
+}
+
+class CompilerError {
+ val test = new DynTest
+ test.crushTheCompiler(a = 1, b = 2)
+} \ No newline at end of file
diff --git a/test/files/neg/t8006.check b/test/files/neg/t8006.check
new file mode 100644
index 0000000000..fbac26e3ad
--- /dev/null
+++ b/test/files/neg/t8006.check
@@ -0,0 +1,6 @@
+t8006.scala:3: error: too many arguments for method applyDynamicNamed: (value: (String, Any))String
+error after rewriting to X.this.d.applyDynamicNamed("meth")(scala.Tuple2("value1", 10), scala.Tuple2("value2", 100))
+possible cause: maybe a wrong Dynamic method signature?
+ d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed
+ ^
+one error found
diff --git a/test/files/neg/t8006.scala b/test/files/neg/t8006.scala
new file mode 100644
index 0000000000..b2f71c1587
--- /dev/null
+++ b/test/files/neg/t8006.scala
@@ -0,0 +1,8 @@
+object X {
+ val d = new D
+ d.meth(value1 = 10, value2 = 100) // two arguments here, but only one is allowed
+}
+import language.dynamics
+class D extends Dynamic {
+ def applyDynamicNamed(name: String)(value: (String, Any)) = name
+} \ No newline at end of file