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)) {
JetValueArgumentList argumentList = superCall.getValueArgumentList();
if (argumentList != null) {
argumentList.accept(visitor);
if (superCall != null) {
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext);
ClassDescriptor superClass = ((ConstructorDescriptor) resolvedCall.getResultingDescriptor()).getContainingDeclaration();
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) {
if (superIndex >= superParameters.size()) break;
JvmMethodParameterKind superKind = superParameters.get(superIndex).getKind();
JvmMethodParameterKind kind = parameter.getKind();
Type type = parameter.getAsmType();
// Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below
if (superParameters.get(superIndex).getKind() == JvmMethodParameterKind.VALUE &&
kind == JvmMethodParameterKind.SUPER_CALL_PARAM) {
if (superKind == JvmMethodParameterKind.VALUE && kind == JvmMethodParameterKind.SUPER_CALL_PARAM) {
// Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below
break;
}
if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL ||
(kind == JvmMethodParameterKind.OUTER && superConstructor.getContainingDeclaration().isInner())) {
if (superKind == JvmMethodParameterKind.OUTER) {
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);
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);
}
@TestMetadata("localClassOuterDiffersFromInnerOuter.kt")
public void testLocalClassOuterDiffersFromInnerOuter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/superConstructorCall/localClassOuterDiffersFromInnerOuter.kt");
doTest(fileName);
}
@TestMetadata("localExtendsLocalWithClosure.kt")
public void testLocalExtendsLocalWithClosure() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/superConstructorCall/localExtendsLocalWithClosure.kt");
@@ -6284,6 +6290,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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")