summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/TreeGen.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala11
-rw-r--r--test/files/run/bug4753.check1
-rw-r--r--test/files/run/bug4753.scala12
4 files changed, 24 insertions, 3 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala
index 9d48d9d299..c17ab8be63 100644
--- a/src/compiler/scala/reflect/internal/TreeGen.scala
+++ b/src/compiler/scala/reflect/internal/TreeGen.scala
@@ -226,6 +226,9 @@ abstract class TreeGen {
* that the type given by classOf[T] is too strong and should be
* weakened so as not to suggest that classOf[List[String]] is any
* different from classOf[List[Int]].
+ *
+ * !!! See deconstMap in Erasure for one bug this encoding has induced:
+ * I would be very surprised if there aren't more.
*/
def mkClassOf(tp: Type): Tree =
Literal(Constant(tp)) setType ConstantType(Constant(tp))
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 21bf696077..1c6e2e9f90 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -527,10 +527,15 @@ abstract class Erasure extends AddInterfaces
}
val deconstMap = new TypeMap {
+ // For some reason classOf[Foo] creates ConstantType(Constant(tpe)) with an actual Type for tpe,
+ // which is later translated to a Class. Unfortunately that means we have bugs like the erasure
+ // of Class[Foo] and classOf[Bar] not being seen as equivalent, leading to duplicate method
+ // generation and failing bytecode. See ticket #4753.
def apply(tp: Type): Type = tp match {
- case PolyType(_, _) => mapOver(tp)
- case MethodType(_, _) => mapOver(tp) // nullarymethod was eliminated during uncurry
- case _ => tp.deconst
+ case PolyType(_, _) => mapOver(tp)
+ case MethodType(_, _) => mapOver(tp) // nullarymethod was eliminated during uncurry
+ case ConstantType(Constant(_: Type)) => ClassClass.tpe // all classOfs erase to Class
+ case _ => tp.deconst
}
}
// Methods on Any/Object which we rewrite here while we still know what
diff --git a/test/files/run/bug4753.check b/test/files/run/bug4753.check
new file mode 100644
index 0000000000..7b19ee8df2
--- /dev/null
+++ b/test/files/run/bug4753.check
@@ -0,0 +1 @@
+boolean
diff --git a/test/files/run/bug4753.scala b/test/files/run/bug4753.scala
new file mode 100644
index 0000000000..cfb252cbe5
--- /dev/null
+++ b/test/files/run/bug4753.scala
@@ -0,0 +1,12 @@
+trait A {
+ val actualType: Class[_]
+}
+trait B extends A {
+ final val actualType = classOf[Boolean]
+}
+
+object Test extends B {
+ def main(args: Array[String]): Unit = {
+ println(actualType)
+ }
+}