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();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) {
|
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();
|
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
|
||||||
if (isSingleton) {
|
if (isSingleton) {
|
||||||
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
|
if (calleeContainingClass.equals(context.getThisDescriptor()) &&
|
||||||
@@ -2662,10 +2668,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
|
if (!forceOuter && isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
|
||||||
return castToRequiredTypeOfInterfaceIfNeeded(result, 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
|
//for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer
|
||||||
if (inStartConstructorContext) {
|
if (inStartConstructorContext) {
|
||||||
result = cur.getOuterExpression(result, false);
|
result = cur.getOuterExpression(result, false);
|
||||||
@@ -3441,10 +3449,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
if (dispatchReceiver != null) {
|
if (dispatchReceiver != null) {
|
||||||
Type receiverType = typeMapper.mapType(dispatchReceiver.getType());
|
Type receiverType = typeMapper.mapType(dispatchReceiver.getType());
|
||||||
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
||||||
boolean callSuper = containingDeclaration.isInner() &&
|
boolean callSuper = containingDeclaration.isInner() && receiver instanceof ClassReceiver;
|
||||||
receiver instanceof ClassReceiver &&
|
|
||||||
((ClassReceiver) receiver).getDeclarationDescriptor().getOriginal() !=
|
|
||||||
containingDeclaration.getOriginal();
|
|
||||||
generateReceiverValue(receiver, callSuper).put(receiverType, v);
|
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",
|
String.format("Non-outer parameter incorrectly mapped to outer for %s: %s vs %s",
|
||||||
constructorDescriptor, parameters, superParameters);
|
constructorDescriptor, parameters, superParameters);
|
||||||
// Super constructor requires OUTER parameter, but our OUTER instance may be different from what is expected by the super
|
// 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
|
// constructor. We need to traverse our outer classes from the bottom up, to find the needed class. See innerExtendsOuter.kt
|
||||||
// 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();
|
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);
|
outer.put(outer.type, codegen.v);
|
||||||
superIndex++;
|
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:
|
// 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.
|
// 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.
|
// 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 class Outer(vararg val chars: Char) {
|
||||||
open inner class Inner(val s: String): Outer(s[0], s[1]) {
|
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);
|
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")
|
@TestMetadata("properOuter.kt")
|
||||||
public void testProperOuter() throws Exception {
|
public void testProperOuter() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/properOuter.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/properOuter.kt");
|
||||||
doTest(fileName);
|
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);
|
doTestWithJava(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClass")
|
||||||
|
public void testInnerClass() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/innerClass/");
|
||||||
|
doTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("interfaceCompanion")
|
@TestMetadata("interfaceCompanion")
|
||||||
public void testInterfaceCompanion() throws Exception {
|
public void testInterfaceCompanion() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/interfaceCompanion/");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/interfaceCompanion/");
|
||||||
|
|||||||
Reference in New Issue
Block a user