summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-02-12 11:05:14 -0800
committerPaul Phillips <paulp@improving.org>2013-02-12 11:05:14 -0800
commitc26cc531f655cfa5b27ffb8ab25adc7ffb97aa71 (patch)
tree9c3559d40b7ea6135c39085b19b6c2702e8625d2
parent0c59fc9a1416cf5c45699111e8857adb03f7f0d4 (diff)
downloadscala-c26cc531f655cfa5b27ffb8ab25adc7ffb97aa71.tar.gz
scala-c26cc531f655cfa5b27ffb8ab25adc7ffb97aa71.tar.bz2
scala-c26cc531f655cfa5b27ffb8ab25adc7ffb97aa71.zip
SI-6355, weakend implementation restriction on applyDynamic.
I realized one can successfully call an overloaded applyDynamic, under conditions such as these: def applyDynamic[T1](m: String)(x1: T1): Any = 1 def applyDynamic[T1, T2](m: String)(x: T1, y: T2): Any = 2 def applyDynamic[T1, T2, T3](m: String)(x: T1, y: T2, z: T3): Any = 3 So I weakened the overloading restriction to allow overloading if each method has a distinct number of type parameters. This very likely still allows the creation of uncallable overloads, but an overly restrictive rule is worse. If the overload cannot be called, it will still be discovered at the call site.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala11
-rw-r--r--test/files/neg/t6355.check7
-rw-r--r--test/files/neg/t6355.scala6
-rw-r--r--test/files/pos/t6355pos.scala16
4 files changed, 32 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 7c60ce275a..60a73036f8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -136,9 +136,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// Check for doomed attempt to overload applyDynamic
if (clazz isSubClass DynamicClass) {
- clazz.info member nme.applyDynamic match {
- case sym if sym.isOverloaded => unit.error(sym.pos, "implementation restriction: applyDynamic cannot be overloaded")
- case _ =>
+ for ((_, m1 :: m2 :: _) <- (clazz.info member nme.applyDynamic).alternatives groupBy (_.typeParams.length)) {
+ unit.error(m1.pos, "implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)")
}
}
@@ -1237,12 +1236,12 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
*/
private def checkMigration(sym: Symbol, pos: Position) = {
if (sym.hasMigrationAnnotation) {
- val changed = try
+ val changed = try
settings.Xmigration.value < ScalaVersion(sym.migrationVersion.get)
catch {
- case e : NumberFormatException =>
+ case e : NumberFormatException =>
unit.warning(pos, s"${sym.fullLocationString} has an unparsable version number: ${e.getMessage()}")
- // if we can't parse the format on the migration annotation just conservatively assume it changed
+ // if we can't parse the format on the migration annotation just conservatively assume it changed
true
}
if (changed)
diff --git a/test/files/neg/t6355.check b/test/files/neg/t6355.check
index c1fa147f52..607829d99a 100644
--- a/test/files/neg/t6355.check
+++ b/test/files/neg/t6355.check
@@ -1,4 +1,7 @@
-t6355.scala:12: error: implementation restriction: applyDynamic cannot be overloaded
+t6355.scala:12: error: implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)
def applyDynamic(name: String)(x: Int): Int = 2
^
-one error found
+t6355.scala:18: error: implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)
+ def applyDynamic[T1, T2](name: String)(x: String, y: T1, z: T2): Int = 3
+ ^
+two errors found
diff --git a/test/files/neg/t6355.scala b/test/files/neg/t6355.scala
index 3007dc49f6..0500ed04c6 100644
--- a/test/files/neg/t6355.scala
+++ b/test/files/neg/t6355.scala
@@ -11,3 +11,9 @@ class A extends Dynamic {
def applyDynamic(name: String)(s: String): Int = 1
def applyDynamic(name: String)(x: Int): Int = 2
}
+
+class B extends Dynamic {
+ def applyDynamic[T1](name: String)(x: T1): Int = 1
+ def applyDynamic[T1, T2](name: String)(x: T1, y: T2): Int = 2
+ def applyDynamic[T1, T2](name: String)(x: String, y: T1, z: T2): Int = 3
+}
diff --git a/test/files/pos/t6355pos.scala b/test/files/pos/t6355pos.scala
new file mode 100644
index 0000000000..c0e740dd68
--- /dev/null
+++ b/test/files/pos/t6355pos.scala
@@ -0,0 +1,16 @@
+import scala.language.dynamics
+
+class A extends Dynamic {
+ def applyDynamic[T1](method: String)(x1: T1): Any = 1
+ def applyDynamic[T1, T2](method: String)(x: T1, y: T2): Any = 2
+ def applyDynamic[T1, T2, T3](method: String)(x: T1, y: T2, z: T3): Any = 3
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val x = new A
+ println(x[Int](5))
+ println(x[Int, String](5, "a"))
+ println(x[Int, String, Int](5, "a", 5))
+ }
+}