Fix for KT-7421: Unable to inherit from inner class
Fix for KT-6708: Compiler Error when extending open inner class: "java.lang.RuntimeException: Error generating primary constructor of class InnerB with kind IMPLEMENTATION" #KT-7421 Fixed #KT-6708 Fixed
This commit is contained in:
@@ -2635,8 +2635,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) {
|
||||
return generateThisOrOuter(calleeContainingClass, isSuper, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
||||
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
|
||||
if (isSingleton) {
|
||||
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
|
||||
@@ -2662,10 +2668,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
|
||||
if (!forceOuter && isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
|
||||
return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass);
|
||||
}
|
||||
|
||||
forceOuter = false;
|
||||
|
||||
//for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer
|
||||
if (inStartConstructorContext) {
|
||||
result = cur.getOuterExpression(result, false);
|
||||
@@ -3441,10 +3449,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (dispatchReceiver != null) {
|
||||
Type receiverType = typeMapper.mapType(dispatchReceiver.getType());
|
||||
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
||||
boolean callSuper = containingDeclaration.isInner() &&
|
||||
receiver instanceof ClassReceiver &&
|
||||
((ClassReceiver) receiver).getDeclarationDescriptor().getOriginal() !=
|
||||
containingDeclaration.getOriginal();
|
||||
boolean callSuper = containingDeclaration.isInner() && receiver instanceof ClassReceiver;
|
||||
generateReceiverValue(receiver, callSuper).put(receiverType, v);
|
||||
}
|
||||
|
||||
|
||||
@@ -1435,11 +1435,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
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
|
||||
// constructor. We need to traverse our outer classes from the bottom up, to find the needed class. See innerExtendsOuter.kt
|
||||
ClassDescriptor outerForSuper = (ClassDescriptor) superConstructor.getContainingDeclaration().getContainingDeclaration();
|
||||
StackValue outer = codegen.generateThisOrOuter(outerForSuper, false);
|
||||
StackValue outer = codegen.generateThisOrOuter(outerForSuper, true, true);
|
||||
outer.put(outer.type, codegen.v);
|
||||
superIndex++;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
open class A() {
|
||||
open inner class InnerA
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
inner class InnerB : A.InnerA()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
B().InnerB()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
open class A(val s: String) {
|
||||
|
||||
val z = s
|
||||
|
||||
fun test() = s
|
||||
|
||||
open inner class B(s: String): A(s) {
|
||||
fun testB() = z + test()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val res = A("Fail").B("OK").testB()
|
||||
return if (res == "OKOK") "OK" else res;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// When inner class extends its outer, there are two instances of the outer present in the inner:
|
||||
// the enclosing one and the one in the super call.
|
||||
// Here we test that symbols are resolved to the instance created via the super call.
|
||||
// This differs from Java, so this test may change when we revisit code generation of inner classes
|
||||
|
||||
open class Outer(vararg val chars: Char) {
|
||||
open inner class Inner(val s: String): Outer(s[0], s[1]) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
public abstract class JavaClass {
|
||||
public abstract InnerClass onCreateInner();
|
||||
|
||||
public class InnerClass {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class MyWallpaperService : JavaClass() {
|
||||
override fun onCreateInner(): JavaClass.InnerClass = MyEngine()
|
||||
|
||||
private inner class MyEngine : JavaClass.InnerClass()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return if (MyWallpaperService().onCreateInner() != null) return "OK" else "fail"
|
||||
}
|
||||
+12
@@ -1710,11 +1710,23 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt6708.kt")
|
||||
public void testKt6708() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/kt6708.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("properOuter.kt")
|
||||
public void testProperOuter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/properOuter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("properSuperLinking.kt")
|
||||
public void testProperSuperLinking() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/properSuperLinking.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -71,6 +71,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerClass")
|
||||
public void testInnerClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/innerClass/");
|
||||
doTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("interfaceCompanion")
|
||||
public void testInterfaceCompanion() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/interfaceCompanion/");
|
||||
|
||||
Reference in New Issue
Block a user