Fix for KT-3335: Creating imported super class' inner class fails in codegen
#KT-3335 Fixed
This commit is contained in:
@@ -2562,7 +2562,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue) {
|
||||
public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue, boolean isSuper) {
|
||||
if (receiverValue instanceof ClassReceiver) {
|
||||
ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor();
|
||||
if (DescriptorUtils.isCompanionObject(receiverDescriptor)) {
|
||||
@@ -2575,7 +2575,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
else {
|
||||
return StackValue.thisOrOuter(this, receiverDescriptor, false, isEnumEntry(receiverDescriptor));
|
||||
return StackValue.thisOrOuter(this, receiverDescriptor, isSuper, isEnumEntry(receiverDescriptor));
|
||||
}
|
||||
}
|
||||
else if (receiverValue instanceof ScriptReceiver) {
|
||||
@@ -3437,14 +3437,20 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
ConstructorDescriptor constructor = getConstructorDescriptor(resolvedCall);
|
||||
|
||||
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
|
||||
ClassDescriptor containingDeclaration = constructor.getContainingDeclaration();
|
||||
if (dispatchReceiver != null) {
|
||||
Type receiverType = typeMapper.mapType(dispatchReceiver.getType());
|
||||
generateReceiverValue(resolvedCall.getDispatchReceiver()).put(receiverType, v);
|
||||
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
|
||||
boolean callSuper = containingDeclaration.isInner() &&
|
||||
receiver instanceof ClassReceiver &&
|
||||
((ClassReceiver) receiver).getDeclarationDescriptor().getOriginal() !=
|
||||
containingDeclaration.getOriginal();
|
||||
generateReceiverValue(receiver, callSuper).put(receiverType, v);
|
||||
}
|
||||
|
||||
// Resolved call to local class constructor doesn't have dispatchReceiver, so we need to generate closure on stack
|
||||
// See StackValue.receiver for more info
|
||||
pushClosureOnStack(constructor.getContainingDeclaration(), dispatchReceiver == null, defaultCallGenerator);
|
||||
pushClosureOnStack(containingDeclaration, dispatchReceiver == null, defaultCallGenerator);
|
||||
|
||||
constructor = SamCodegenUtil.resolveSamAdapter(constructor);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(constructor, false);
|
||||
|
||||
@@ -535,7 +535,7 @@ public abstract class StackValue {
|
||||
) {
|
||||
if (receiver == none()) {
|
||||
if (receiverValue.exists()) {
|
||||
return codegen.generateReceiverValue(receiverValue);
|
||||
return codegen.generateReceiverValue(receiverValue, false);
|
||||
}
|
||||
else if (isLocalFunCall(callableMethod) && !isExtension) {
|
||||
StackValue value = codegen.findLocalOrCapturedValue(resolvedCall.getResultingDescriptor().getOriginal());
|
||||
@@ -862,7 +862,7 @@ public abstract class StackValue {
|
||||
|
||||
if (resolvedSetCall.getDispatchReceiver().exists()) {
|
||||
if (resolvedSetCall.getExtensionReceiver().exists()) {
|
||||
codegen.generateReceiverValue(resolvedSetCall.getDispatchReceiver()).put(OBJECT_TYPE, v);
|
||||
codegen.generateReceiverValue(resolvedSetCall.getDispatchReceiver(), false).put(OBJECT_TYPE, v);
|
||||
}
|
||||
v.load(realReceiverIndex, realReceiverType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
open class A(val value: String) {
|
||||
inner class B(val s: String) {
|
||||
val result = value + "_" + s
|
||||
}
|
||||
}
|
||||
|
||||
class C : A("fromC") {
|
||||
fun classReceiver() = B("OK")
|
||||
fun superReceiver() = super.B("OK")
|
||||
|
||||
fun newAReceiver() = A("fromA").B("OK")
|
||||
fun aReceiver(): B {
|
||||
val a = A("fromA")
|
||||
return a.B("OK")
|
||||
}
|
||||
|
||||
fun A.extReceiver() = this.B("OK")
|
||||
fun extReceiver() = A("fromA").extReceiver()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val receiver = C()
|
||||
var result = receiver.classReceiver().result
|
||||
if (result != "fromC_OK") return "fail 1: $result"
|
||||
|
||||
result = receiver.superReceiver().result
|
||||
if (result != "fromC_OK") return "fail 2: $result"
|
||||
|
||||
|
||||
result = receiver.aReceiver().result
|
||||
if (result != "fromA_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.newAReceiver().result
|
||||
if (result != "fromA_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.extReceiver().result
|
||||
if (result != "fromA_OK") return "fail 3: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
open class A(val value: String) {
|
||||
inner class B(val s: String) {
|
||||
val result = value + "_" + s
|
||||
}
|
||||
}
|
||||
|
||||
class C : A("fromC") {
|
||||
|
||||
inner class X: A("fromX") {
|
||||
fun classReceiver() = B("OK")
|
||||
fun superReceiver() = super.B("OK")
|
||||
fun superXReceiver() = super@X.B("OK")
|
||||
fun superXCastReceiver() = (this@X as A).B("OK")
|
||||
|
||||
fun superCReceiver() = super@C.B("OK")
|
||||
fun superCCastReceiver() = (this@C as A).B("OK")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val receiver = C().X()
|
||||
var result = receiver.classReceiver().result
|
||||
if (result != "fromX_OK") return "fail 1: $result"
|
||||
|
||||
result = receiver.superReceiver().result
|
||||
if (result != "fromX_OK") return "fail 2: $result"
|
||||
|
||||
result = receiver.superXReceiver().result
|
||||
if (result != "fromX_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.superXCastReceiver().result
|
||||
if (result != "fromX_OK") return "fail 4: $result"
|
||||
|
||||
|
||||
result = receiver.superCReceiver().result
|
||||
if (result != "fromC_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.superCCastReceiver().result
|
||||
if (result != "fromC_OK") return "fail 4: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
class C(val value: String = "C") {
|
||||
|
||||
inner class B(val s: String) {
|
||||
val result = value + "_" + s
|
||||
}
|
||||
|
||||
fun classReceiver() = B("OK")
|
||||
|
||||
fun newCReceiver() = C("newC").B("OK")
|
||||
fun cReceiver(): B {
|
||||
val c = C("newC")
|
||||
return c.B("OK")
|
||||
}
|
||||
|
||||
fun C.extReceiver1() = this.B("OK")
|
||||
fun extReceiver() = C("newC").extReceiver1()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val receiver = C()
|
||||
var result = receiver.classReceiver().result
|
||||
if (result != "C_OK") return "fail 1: $result"
|
||||
|
||||
result = receiver.cReceiver().result
|
||||
if (result != "newC_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.newCReceiver().result
|
||||
if (result != "newC_OK") return "fail 3: $result"
|
||||
|
||||
result = receiver.extReceiver().result
|
||||
if (result != "newC_OK") return "fail 3: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
open class A(val s: String) {
|
||||
open inner class B(val s: String) {
|
||||
fun testB() = s + this@A.s
|
||||
}
|
||||
|
||||
open inner class C(): A("C") {
|
||||
fun testC() =
|
||||
B("B_").testB()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val res = A("A").C().testC()
|
||||
return if (res == "B_C") "OK" else res;
|
||||
}
|
||||
+33
@@ -1683,6 +1683,39 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/typedDelegation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/classes/inner")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Inner extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInInner() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/classes/inner"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("instantiateInDerived.kt")
|
||||
public void testInstantiateInDerived() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/instantiateInDerived.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("instantiateInDerivedLabeled.kt")
|
||||
public void testInstantiateInDerivedLabeled() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/instantiateInDerivedLabeled.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("instantiateInSameClass.kt")
|
||||
public void testInstantiateInSameClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/inner/instantiateInSameClass.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("compiler/testData/codegen/box/closures")
|
||||
|
||||
Reference in New Issue
Block a user