8000 SI-10069 Fix code gen errors with array updates, Nothing · retronym/scala@880aec0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 880aec0

Browse files
committed
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.
1 parent 73678d4 commit 880aec0

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
168168
} else if (scalaPrimitives.isArraySet(code)) {
169169
val List(a1, a2) = args
170170
genLoad(a1, INT)
171-
genLoad(a2)
171+
genLoad(a2, elementType)
172172
generatedType = UNIT
173173
bc.astore(elementType)
174174
} else {
@@ -630,7 +630,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
630630
generatedType = methodBTypeFromSymbol(fun.symbol).returnType
631631

632632
case Apply(fun, List(expr)) if currentRun.runDefinitions.isBox(fun.symbol) =>
633-
val nativeKind = tpeTK(expr)
633+
val nativeKind = typeToBType(fun.symbol.firstParam.info)
634634
genLoad(expr, nativeKind)
635635
val MethodNameAndType(mname, methodType) = srBoxesRuntimeBoxToMethods(nativeKind)
636636
bc.invokestatic(srBoxesRunTimeRef.internalName, mname, methodType.descriptor, itf = false, app.pos)

test/files/run/t10069.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
object Expected extends Exception
2+
object Test {
3+
def throwExpected: Nothing = throw Expected
4+
def foo0(a: Array[Double]) = { // does compile for Int instead of Double
5+
val v = 42
6+
a(0) = throwExpected // was crash in code gen: java.lang.NegativeArraySizeException
7+
}
8+
9+
def foo1(a: Array[Double]) = { // does compile for Int instead of Double
10+
a(0) = throwExpected // was VerifyError at runtime
11+
}
12+
13+
def foo2(a: Array[Int]) = { // does compile for Int instead of Double
14+
a(0) = throwExpected // was VerifyError at runtime
15+
}
16+
17+
def foo3(a: Array[String]) = { // does compile for Int instead of Double
18+
a(0) = throwExpected // was already working
19+
}
20+
21+
22+
def main(args: Array[String]): Unit = {
23+
check(foo0(new Array[Double](1)))
24+
check(foo1(new Array[Double](1)))
25+
check(foo2(new Array[Int](1)))
26+
check(foo3(new Array[String](1)))
27+
}
28+
def check(f: => Any) {
29+
try {f ; sys.error("no exception thrown")
30+
} catch {
31+
case Expected =>
32+
}
33+
}
34+
}

test/files/run/t10069b.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
try {
4+
Int.box(???) // crashed the compiler: java.util.NoSuchElementException: key not found: Lscala/runtime/Nothing$;
5+
sys.error("no exception")
6+
} catch {
7+
case _: NotImplementedError =>
8+
// oka
9+
case e: Throwable =>
10+
sys.error("wrong exception: " + e)
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)
0