Pass correct outer instance in complex case of inheritance

#KT-5343 Fixed
This commit is contained in:
Alexander Udalov
2014-10-15 19:15:47 +04:00
parent 61674fb3d9
commit 159878e09d
4 changed files with 74 additions and 9 deletions
@@ -1392,10 +1392,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
if (superCall != null && !isAnonymousObject(descriptor)) { if (superCall != null) {
JetValueArgumentList argumentList = superCall.getValueArgumentList(); ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext);
if (argumentList != null) { ClassDescriptor superClass = ((ConstructorDescriptor) resolvedCall.getResultingDescriptor()).getContainingDeclaration();
argumentList.accept(visitor); if (superClass.isInner()) {
constructorContext.lookupInContext(superClass.getContainingDeclaration(), StackValue.local(0, OBJECT_TYPE), state, true);
}
if (!isAnonymousObject(descriptor)) {
JetValueArgumentList argumentList = superCall.getValueArgumentList();
if (argumentList != null) {
argumentList.accept(visitor);
}
} }
} }
} }
@@ -1494,17 +1502,29 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (JvmMethodParameterSignature parameter : parameters) { for (JvmMethodParameterSignature parameter : parameters) {
if (superIndex >= superParameters.size()) break; if (superIndex >= superParameters.size()) break;
JvmMethodParameterKind superKind = superParameters.get(superIndex).getKind();
JvmMethodParameterKind kind = parameter.getKind(); JvmMethodParameterKind kind = parameter.getKind();
Type type = parameter.getAsmType(); Type type = parameter.getAsmType();
// Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below if (superKind == JvmMethodParameterKind.VALUE && kind == JvmMethodParameterKind.SUPER_CALL_PARAM) {
if (superParameters.get(superIndex).getKind() == JvmMethodParameterKind.VALUE && // Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below
kind == JvmMethodParameterKind.SUPER_CALL_PARAM) {
break; break;
} }
if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL || if (superKind == JvmMethodParameterKind.OUTER) {
(kind == JvmMethodParameterKind.OUTER && superConstructor.getContainingDeclaration().isInner())) { assert kind == JvmMethodParameterKind.OUTER || kind == JvmMethodParameterKind.SUPER_CALL_PARAM :
String.format("Non-outer parameter incorrectly mapped to outer for %s: %s vs %s",
constructorDescriptor, parameters, superParameters);
// Super constructor requires OUTER parameter, but our OUTER instance may be different from what is expected by the super
// constructor. We need to traverse our outer classes from the bottom up, to find the needed class
// TODO: isSuper should be "true" but this makes some tests on inner classes extending outer fail
// See innerExtendsOuter.kt, semantics of inner classes extending their outer should be changed to be as in Java
ClassDescriptor outerForSuper = (ClassDescriptor) superConstructor.getContainingDeclaration().getContainingDeclaration();
StackValue outer = codegen.generateThisOrOuter(outerForSuper, false);
outer.put(outer.type, codegen.v);
superIndex++;
}
else if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) {
iv.load(offset, type); iv.load(offset, type);
superIndex++; superIndex++;
} }
@@ -0,0 +1,17 @@
class A {
fun bar(): Any {
return {
{
class Local : Inner() {
override fun toString() = foo()
}
Local()
}()
}()
}
open inner class Inner
fun foo() = "OK"
}
fun box(): String = A().bar().toString()
@@ -0,0 +1,16 @@
class A {
fun bar(): Any {
return {
{
object : Inner() {
override fun toString() = foo()
}
}()
}()
}
open inner class Inner
fun foo() = "OK"
}
fun box(): String = A().bar().toString()
@@ -6224,6 +6224,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("localClassOuterDiffersFromInnerOuter.kt")
public void testLocalClassOuterDiffersFromInnerOuter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/superConstructorCall/localClassOuterDiffersFromInnerOuter.kt");
doTest(fileName);
}
@TestMetadata("localExtendsLocalWithClosure.kt") @TestMetadata("localExtendsLocalWithClosure.kt")
public void testLocalExtendsLocalWithClosure() throws Exception { public void testLocalExtendsLocalWithClosure() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt");
@@ -6284,6 +6290,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("objectOuterDiffersFromInnerOuter.kt")
public void testObjectOuterDiffersFromInnerOuter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/superConstructorCall/objectOuterDiffersFromInnerOuter.kt");
doTest(fileName);
}
} }
@TestMetadata("compiler/testData/codegen/box/toArray") @TestMetadata("compiler/testData/codegen/box/toArray")