Pass correct outer instance in complex case of inheritance
#KT-5343 Fixed
This commit is contained in:
@@ -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++;
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -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()
|
||||||
+16
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user