Fix initialization of inner class instances in enum entries
In an inner class of the enum entry class, enum entry reference should be generated as an outer 'this', not as a enum entry access, because enum entry itself may be not initialized yet.
This commit is contained in:
@@ -2534,6 +2534,23 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return generateThisOrOuter(calleeContainingClass, isSuper, false);
|
return generateThisOrOuter(calleeContainingClass, isSuper, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInInnerClassConstructorContext(@NotNull ClassDescriptor calleeContainingClass) {
|
||||||
|
if (!(context instanceof ConstructorContext)) return false;
|
||||||
|
|
||||||
|
CallableMemberDescriptor contextDescriptor = context.getContextDescriptor();
|
||||||
|
assert contextDescriptor instanceof ConstructorDescriptor :
|
||||||
|
"Constructor descriptor expected: " + contextDescriptor;
|
||||||
|
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) contextDescriptor;
|
||||||
|
|
||||||
|
ClassDescriptor classDescriptor = constructorDescriptor.getConstructedClass();
|
||||||
|
if (!classDescriptor.isInner()) return false;
|
||||||
|
|
||||||
|
while (classDescriptor != null && classDescriptor.isInner()) {
|
||||||
|
classDescriptor = DescriptorUtils.getContainingClass(classDescriptor);
|
||||||
|
}
|
||||||
|
return classDescriptor == calleeContainingClass;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
||||||
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
|
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
|
||||||
@@ -2543,7 +2560,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
|
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
|
||||||
}
|
}
|
||||||
else if (isEnumEntry(calleeContainingClass)) {
|
else if (isEnumEntry(calleeContainingClass)) {
|
||||||
return StackValue.enumEntry(calleeContainingClass, typeMapper);
|
if (!isInInnerClassConstructorContext(calleeContainingClass)) {
|
||||||
|
return StackValue.enumEntry(calleeContainingClass, typeMapper);
|
||||||
|
}
|
||||||
|
// else fall-through
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return StackValue.singleton(calleeContainingClass, typeMapper);
|
return StackValue.singleton(calleeContainingClass, typeMapper);
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// LANGUAGE_VERSION: 1.2
|
||||||
|
|
||||||
|
enum class A {
|
||||||
|
X {
|
||||||
|
val x = "OK"
|
||||||
|
|
||||||
|
inner class Inner {
|
||||||
|
val y = x
|
||||||
|
}
|
||||||
|
|
||||||
|
val z = Inner()
|
||||||
|
|
||||||
|
override val test: String
|
||||||
|
get() = z.y
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract val test: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = A.X.test
|
||||||
+6
@@ -7811,6 +7811,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClassInEnumEntryClass.kt")
|
||||||
|
public void testInnerClassInEnumEntryClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerClassInEnumEntryClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("innerWithExistingClassObject.kt")
|
@TestMetadata("innerWithExistingClassObject.kt")
|
||||||
public void testInnerWithExistingClassObject() throws Exception {
|
public void testInnerWithExistingClassObject() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||||
|
|||||||
@@ -7811,6 +7811,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClassInEnumEntryClass.kt")
|
||||||
|
public void testInnerClassInEnumEntryClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerClassInEnumEntryClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("innerWithExistingClassObject.kt")
|
@TestMetadata("innerWithExistingClassObject.kt")
|
||||||
public void testInnerWithExistingClassObject() throws Exception {
|
public void testInnerWithExistingClassObject() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||||
|
|||||||
@@ -7811,6 +7811,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClassInEnumEntryClass.kt")
|
||||||
|
public void testInnerClassInEnumEntryClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerClassInEnumEntryClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("innerWithExistingClassObject.kt")
|
@TestMetadata("innerWithExistingClassObject.kt")
|
||||||
public void testInnerWithExistingClassObject() throws Exception {
|
public void testInnerWithExistingClassObject() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||||
|
|||||||
@@ -8609,6 +8609,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClassInEnumEntryClass.kt")
|
||||||
|
public void testInnerClassInEnumEntryClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerClassInEnumEntryClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("innerWithExistingClassObject.kt")
|
@TestMetadata("innerWithExistingClassObject.kt")
|
||||||
public void testInnerWithExistingClassObject() throws Exception {
|
public void testInnerWithExistingClassObject() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user