Skip to content

Commit c2481d7

Browse files
committed
Fix code gen for Outer.super[Q].foo
Consider class B extends T { class C { B.super[T].f }} After flatten, that call is ` B$C.this.$outer().super[T].f()`. In 2.11, mixin translates this to `A$class.f(B$C.this.$outer())`. In 2.12, the tree is passed unchanged to the backend. In `genApply` we assumed that in `Apply(Select(Super(qual, ... )))`, `qual` is a `This` tree, so we just emitted `ALOAD_0`, which caused the `$outer()` call to get lost. Now we invoke `genLoad(qual)`. Fixes scala/bug#10290.
1 parent 0b150b7 commit c2481d7

File tree

2 files changed

+38
-16
lines changed

2 files changed

+38
-16
lines changed

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

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,12 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
317317
}
318318
else {
319319
mnode.visitVarInsn(asm.Opcodes.ALOAD, 0)
320-
generatedType =
321-
if (tree.symbol == ArrayClass) ObjectRef
322-
else classBTypeFromSymbol(claszSymbol)
320+
// When compiling Array.scala, the constructor invokes 1Array.this.super.<init>1. The expectedType
321+
// is `[Object` (computed by typeToBType, the type of This(Array) is `Array[T]`). If we would set
322+
// the generatedType to `Array` below, the call to adapt at the end would fail.
323+
if (tree.symbol != ArrayClass) {
324+
generatedType = classBTypeFromSymbol(claszSymbol)
325+
}
323326
}
324327

325328
case Select(Ident(nme.EMPTY_PACKAGE_NAME), module) =>
@@ -551,7 +554,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
551554

552555
generatedType = genTypeApply()
553556

554-
case Apply(fun @ Select(Super(_, _), _), args) =>
557+
case Apply(fun @ Select(Super(qual, _), _), args) =>
555558
def initModule() {
556559
// we initialize the MODULE$ field immediately after the super ctor
557560
if (!isModuleInitialized &&
@@ -568,13 +571,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
568571
)
569572
}
570573
}
571-
// 'super' call: Note: since constructors are supposed to
572-
// return an instance of what they construct, we have to take
573-
// special care. On JVM they are 'void', and Scala forbids (syntactically)
574-
// to call super constructors explicitly and/or use their 'returned' value.
575-
// therefore, we can ignore this fact, and generate code that leaves nothing
576-
// on the stack (contrary to what the type in the AST says).
577-
mnode.visitVarInsn(asm.Opcodes.ALOAD, 0)
574+
575+
// scala/bug#10290: qual can be `this.$outer()` (not just `this`), so we call genLoad (not jsut ALOAD_0)
576+
genLoad(qual)
578577
genLoadArguments(args, paramTKs(app))
579578
generatedType = genCallMethod(fun.symbol, InvokeStyle.Super, app.pos)
580579
initModule()
@@ -1061,11 +1060,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
10611060
val receiverBType = classBTypeFromSymbol(receiverClass)
10621061
val receiverName = receiverBType.internalName
10631062

1064-
def needsInterfaceCall(sym: Symbol) = {
1065-
sym.isTraitOrInterface ||
1066-
sym.isJavaDefined && sym.isNonBottomSubClass(definitions.ClassfileAnnotationClass)
1067-
}
1068-
10691063
val jname = method.javaSimpleName.toString
10701064
val bmType = methodBTypeFromSymbol(method)
10711065
val mdescr = bmType.descriptor

test/files/run/t10290.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
trait A1 {
2+
private val s = "A1"
3+
def f = s
4+
}
5+
6+
trait A2 {
7+
private val s = "A2"
8+
def f = s
9+
}
10+
11+
class B extends A1 with A2 {
12+
override def f = "B"
13+
class C {
14+
def t1 = B.super[A1].f
15+
def t2 = B.super[A2].f
16+
def t3 = B.this.f
17+
}
18+
}
19+
20+
object Test {
21+
def main(args : Array[String]) : Unit = {
22+
val b = new B
23+
val c = new b.C
24+
assert(c.t1 == "A1")
25+
assert(c.t2 == "A2")
26+
assert(c.t3 == "B")
27+
}
28+
}

0 commit comments

Comments
 (0)