summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-01-18 11:52:45 -0800
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-01-18 11:52:45 -0800
commit6f72ed85c3882d2a8c824a41e6e42d7f33b8d1d6 (patch)
tree283c3f0a57d4820f97c1316159c004be7d009e0c
parent1a63cf8b9b48c98fa754a1eb6dcfe35220016c74 (diff)
parentc6065591c981e38aedf50618faee945a8b1e5423 (diff)
downloadscala-6f72ed85c3882d2a8c824a41e6e42d7f33b8d1d6.tar.gz
scala-6f72ed85c3882d2a8c824a41e6e42d7f33b8d1d6.tar.bz2
scala-6f72ed85c3882d2a8c824a41e6e42d7f33b8d1d6.zip
Merge pull request #1904 from JamesIry/SI-5568_2.10.x
SI-5568 Fixes verify error from getClass on refinement of value type
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala27
-rw-r--r--test/files/run/t5568.check9
-rw-r--r--test/files/run/t5568.scala16
3 files changed, 46 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 7b9b13ae1c..41aada473a 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -340,12 +340,18 @@ abstract class Erasure extends AddInterfaces
case _ => tp.deconst
}
}
- // Methods on Any/Object which we rewrite here while we still know what
- // is a primitive and what arrived boxed.
- private lazy val interceptedMethods = Set[Symbol](Any_##, Object_##, Any_getClass, AnyVal_getClass) ++ (
- // Each value class has its own getClass for ultra-precise class object typing.
+
+ // Each primitive value class has its own getClass for ultra-precise class object typing.
+ private lazy val primitiveGetClassMethods = Set[Symbol](Any_getClass, AnyVal_getClass) ++ (
ScalaValueClasses map (_.tpe member nme.getClass_)
)
+
+ // ## requires a little translation
+ private lazy val poundPoundMethods = Set[Symbol](Any_##, Object_##)
+
+ // Methods on Any/Object which we rewrite here while we still know what
+ // is a primitive and what arrived boxed.
+ private lazy val interceptedMethods = poundPoundMethods ++ primitiveGetClassMethods
// -------- erasure on trees ------------------------------------------
@@ -1136,7 +1142,7 @@ abstract class Erasure extends AddInterfaces
args)
}
} else if (args.isEmpty && interceptedMethods(fn.symbol)) {
- if (fn.symbol == Any_## || fn.symbol == Object_##) {
+ if (poundPoundMethods.contains(fn.symbol)) {
// This is unattractive, but without it we crash here on ().## because after
// erasure the ScalaRunTime.hash overload goes from Unit => Int to BoxedUnit => Int.
// This must be because some earlier transformation is being skipped on ##, but so
@@ -1152,9 +1158,18 @@ abstract class Erasure extends AddInterfaces
} else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
// Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual, typer.resolveClassTag(tree.pos, qual.tpe.widen))))
- } else if (fn.symbol == AnyVal_getClass) {
+ } else if (primitiveGetClassMethods.contains(fn.symbol)) {
+ // if we got here then we're trying to send a primitive getClass method to either
+ // a) an Any, in which cage Object_getClass works because Any erases to object. Or
+ //
+ // b) a non-primitive, e.g. because the qualifier's type is a refinement type where one parent
+ // of the refinement is a primitive and another is AnyRef. In that case
+ // we get a primitive form of _getClass trying to target a boxed value
+ // so we need replace that method name with Object_getClass to get correct behavior.
+ // See SI-5568.
tree setSymbol Object_getClass
} else {
+ debugwarn(s"The symbol '${fn.symbol}' was interecepted but didn't match any cases, that means the intercepted methods set doesn't match the code")
tree
}
} else qual match {
diff --git a/test/files/run/t5568.check b/test/files/run/t5568.check
new file mode 100644
index 0000000000..67aaf16e07
--- /dev/null
+++ b/test/files/run/t5568.check
@@ -0,0 +1,9 @@
+void
+int
+class scala.runtime.BoxedUnit
+class scala.runtime.BoxedUnit
+class java.lang.Integer
+class java.lang.Integer
+5
+5
+5
diff --git a/test/files/run/t5568.scala b/test/files/run/t5568.scala
new file mode 100644
index 0000000000..14599d9ed2
--- /dev/null
+++ b/test/files/run/t5568.scala
@@ -0,0 +1,16 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ // these should give unboxed results
+ println(().getClass)
+ println(5.getClass)
+ // these should give boxed results
+ println(().asInstanceOf[AnyRef with Unit].getClass)
+ println(().asInstanceOf[Unit with AnyRef].getClass)
+ println(5.asInstanceOf[AnyRef with Int].getClass)
+ println(5.asInstanceOf[Int with AnyRef].getClass)
+ //make sure ## wasn't broken
+ println(5.##)
+ println((5.asInstanceOf[AnyRef]).##)
+ println((5:Any).##)
+ }
+}