diff options
author | Paul Phillips <paulp@improving.org> | 2013-02-12 11:05:14 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-02-12 11:05:14 -0800 |
commit | c26cc531f655cfa5b27ffb8ab25adc7ffb97aa71 (patch) | |
tree | 9c3559d40b7ea6135c39085b19b6c2702e8625d2 | |
parent | 0c59fc9a1416cf5c45699111e8857adb03f7f0d4 (diff) | |
download | scala-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.scala | 11 | ||||
-rw-r--r-- | test/files/neg/t6355.check | 7 | ||||
-rw-r--r-- | test/files/neg/t6355.scala | 6 | ||||
-rw-r--r-- | test/files/pos/t6355pos.scala | 16 |
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)) + } +} |