summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Osheim <d_m@plastic-idolatry.com>2012-02-19 00:09:36 -0500
committerErik Osheim <d_m@plastic-idolatry.com>2012-02-19 00:09:36 -0500
commit1df4fc6e59e65b202d98486ca698c721122054d2 (patch)
tree183686c3a4fa2879d51ae5676ad86adbc90886c9
parent1f4f1235920fe87e1b1bdfd042683d9651f1d4f1 (diff)
downloadscala-1df4fc6e59e65b202d98486ca698c721122054d2.tar.gz
scala-1df4fc6e59e65b202d98486ca698c721122054d2.tar.bz2
scala-1df4fc6e59e65b202d98486ca698c721122054d2.zip
Fixed over-optimistic anyrefSpecCache (closes SI-5500).
The basic problem here was that generic type params were getting confused between the various specialized subclasses. For instance, calling typeParamsSubAnyRef(A, C2$mcLI$sp) might return the wrong specialized type param, e.g. C2$mcLZ$sp.A$sp (note the Z instead of the I). The fix is to cache with both the sym (A) and also the clazz (C2$mcLI$sp). This may resolve a whole host of other obscure AnyRef specialization problems.
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala15
-rw-r--r--test/files/run/t5500.check2
-rw-r--r--test/files/run/t5500.scala12
3 files changed, 23 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 8b1d5b3295..d96dff26db 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -87,9 +87,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Map class symbols to the type environments where they were created. */
private val typeEnv = mutable.HashMap[Symbol, TypeEnv]() withDefaultValue emptyEnv
- // holds mappings from regular type parameter symbols to symbols of
- // specialized type parameters which are subtypes of AnyRef
- private val anyrefSpecCache = perRunCaches.newMap[Symbol, Symbol]()
+ // holds mappings from regular type parameter symbols and their class to
+ // symbols of specialized type parameters which are subtypes of AnyRef
+ // e.g. (sym, clazz) => specializedSym
+ private val anyrefSpecCache = perRunCaches.newMap[(Symbol, Symbol), Symbol]()
// holds mappings from members to the type variables in the class
// that they were already specialized for, so that they don't get
@@ -435,7 +436,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* `sym` in the original class. It will create it if needed or use the one from the cache.
*/
private def typeParamSubAnyRef(sym: Symbol, clazz: Symbol) = (
- anyrefSpecCache.getOrElseUpdate(sym,
+ anyrefSpecCache.getOrElseUpdate((sym, clazz),
clazz.newTypeParameter(sym.name append nme.SPECIALIZED_SUFFIX_NAME toTypeName, sym.pos)
setInfo TypeBounds(sym.info.bounds.lo, AnyRefClass.tpe)
).tpe
@@ -447,8 +448,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// remove class type parameters and those of normalized members.
clazz :: decls foreach {
_.tpe match {
- case PolyType(tparams, _) => anyrefSpecCache --= tparams
- case _ => ()
+ case PolyType(tparams, _) => tparams.foreach {
+ s => anyrefSpecCache.remove((s, clazz))
+ }
+ case _ => ()
}
}
)
diff --git a/test/files/run/t5500.check b/test/files/run/t5500.check
new file mode 100644
index 0000000000..19c6dda00e
--- /dev/null
+++ b/test/files/run/t5500.check
@@ -0,0 +1,2 @@
+C1$mcLI$sp
+C2$mcLI$sp
diff --git a/test/files/run/t5500.scala b/test/files/run/t5500.scala
new file mode 100644
index 0000000000..6fbe168a54
--- /dev/null
+++ b/test/files/run/t5500.scala
@@ -0,0 +1,12 @@
+import scala.{specialized => spec}
+
+class C1[@spec(Int, AnyRef) A, @spec(Int, AnyRef) B](v:A, w:B)
+
+class C2[@spec(Unit, Boolean, Byte, Char, Short, Int, Long, Float, Double, AnyRef) A, @spec(Unit, Boolean, Byte, Char, Short, Int, Long, Float, Double, AnyRef) B](v:A, w:B)
+
+object Test {
+ def main(args:Array[String]) {
+ println(new C1("abc", 123).getClass.getName)
+ println(new C2[String, Int]("abc", 123).getClass.getName)
+ }
+}