diff options
-rw-r--r-- | src/compiler/scala/reflect/internal/TreeGen.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 11 | ||||
-rw-r--r-- | test/files/run/bug4753.check | 1 | ||||
-rw-r--r-- | test/files/run/bug4753.scala | 12 |
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) + } +} |