summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2016-11-18 16:49:25 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-12-02 11:09:31 +1000
commit880aec04e82ad3a9a2feb3b83b779f192d84e01e (patch)
treef668cf6c27ce152fd7624e081fac2623812b2d24
parent73678d4dafe250f0b38df2e953787af26b1a4ee3 (diff)
downloadscala-880aec04e82ad3a9a2feb3b83b779f192d84e01e.tar.gz
scala-880aec04e82ad3a9a2feb3b83b779f192d84e01e.tar.bz2
scala-880aec04e82ad3a9a2feb3b83b779f192d84e01e.zip
SI-10069 Fix code gen errors with array updates, Nothing
Crashes in ASM or VerifyErrors used to occur when assigning an expression of type Nothing to an element of a primitive array. This commit adapts the RHS of the assignment to the element type to correct this. `adapt` contains logic to insert an `ATHROW` of the slot of type `Nothing$`, which makes everything line up. The subsequent array stores become dead code and are dropped later on in code gen, so the test case compiles to: public void foo0(double[]); Code: 0: bipush 42 2: istore_2 3: aload_1 4: iconst_0 5: aload_0 6: invokevirtual #30 // Method throwExpected:()Lscala/runtime/Nothing$; 9: athrow I found a similar bug in the emission of primitive unboxing and fixed that too.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala4
-rw-r--r--test/files/run/t10069.scala34
-rw-r--r--test/files/run/t10069b.scala13
3 files changed, 49 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index b0815b0008..c7952ffe94 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -168,7 +168,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
} else if (scalaPrimitives.isArraySet(code)) {
val List(a1, a2) = args
genLoad(a1, INT)
- genLoad(a2)
+ genLoad(a2, elementType)
generatedType = UNIT
bc.astore(elementType)
} else {
@@ -630,7 +630,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
generatedType = methodBTypeFromSymbol(fun.symbol).returnType
case Apply(fun, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) =>
- val nativeKind = tpeTK(expr)
+ val nativeKind = typeToBType(fun.symbol.firstParam.info)
genLoad(expr, nativeKind)
val MethodNameAndType(mname, methodType) = srBoxesRuntimeBoxToMethods(nativeKind)
bc.invokestatic(srBoxesRunTimeRef.internalName, mname, methodType.descriptor, itf = false, app.pos)
diff --git a/test/files/run/t10069.scala b/test/files/run/t10069.scala
new file mode 100644
index 0000000000..4e70b7e814
--- /dev/null
+++ b/test/files/run/t10069.scala
@@ -0,0 +1,34 @@
+object Expected extends Exception
+object Test {
+ def throwExpected: Nothing = throw Expected
+ def foo0(a: Array[Double]) = { // does compile for Int instead of Double
+ val v = 42
+ a(0) = throwExpected // was crash in code gen: java.lang.NegativeArraySizeException
+ }
+
+ def foo1(a: Array[Double]) = { // does compile for Int instead of Double
+ a(0) = throwExpected // was VerifyError at runtime
+ }
+
+ def foo2(a: Array[Int]) = { // does compile for Int instead of Double
+ a(0) = throwExpected // was VerifyError at runtime
+ }
+
+ def foo3(a: Array[String]) = { // does compile for Int instead of Double
+ a(0) = throwExpected // was already working
+ }
+
+
+ def main(args: Array[String]): Unit = {
+ check(foo0(new Array[Double](1)))
+ check(foo1(new Array[Double](1)))
+ check(foo2(new Array[Int](1)))
+ check(foo3(new Array[String](1)))
+ }
+ def check(f: => Any) {
+ try {f ; sys.error("no exception thrown")
+ } catch {
+ case Expected =>
+ }
+ }
+}
diff --git a/test/files/run/t10069b.scala b/test/files/run/t10069b.scala
new file mode 100644
index 0000000000..c9d652bb0c
--- /dev/null
+++ b/test/files/run/t10069b.scala
@@ -0,0 +1,13 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ try {
+ Int.box(???) // crashed the compiler: java.util.NoSuchElementException: key not found: Lscala/runtime/Nothing$;
+ sys.error("no exception")
+ } catch {
+ case _: NotImplementedError =>
+ // oka
+ case e: Throwable =>
+ sys.error("wrong exception: " + e)
+ }
+ }
+}