From 159878e09dff91e35d4abf30366137c8d899e07a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 15 Oct 2014 19:15:47 +0400 Subject: [PATCH] Pass correct outer instance in complex case of inheritance #KT-5343 Fixed --- .../codegen/ImplementationBodyCodegen.java | 38 ++++++++++++++----- .../localClassOuterDiffersFromInnerOuter.kt | 17 +++++++++ .../objectOuterDiffersFromInnerOuter.kt | 16 ++++++++ .../BlackBoxCodegenTestGenerated.java | 12 ++++++ 4 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 compiler/testData/codegen/box/superConstructorCall/localClassOuterDiffersFromInnerOuter.kt create mode 100644 compiler/testData/codegen/box/superConstructorCall/objectOuterDiffersFromInnerOuter.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 7950ec3560a..8f61fe75ba2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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++; } diff --git a/compiler/testData/codegen/box/superConstructorCall/localClassOuterDiffersFromInnerOuter.kt b/compiler/testData/codegen/box/superConstructorCall/localClassOuterDiffersFromInnerOuter.kt new file mode 100644 index 00000000000..cf1db10e27c --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/localClassOuterDiffersFromInnerOuter.kt @@ -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() diff --git a/compiler/testData/codegen/box/superConstructorCall/objectOuterDiffersFromInnerOuter.kt b/compiler/testData/codegen/box/superConstructorCall/objectOuterDiffersFromInnerOuter.kt new file mode 100644 index 00000000000..e6fe2b05cf9 --- /dev/null +++ b/compiler/testData/codegen/box/superConstructorCall/objectOuterDiffersFromInnerOuter.kt @@ -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() diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index e208aa26d70..16bb47a4cf9 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -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")