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);
|
||||
}
|
||||
|
||||
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
|
||||
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper, boolean forceOuter) {
|
||||
boolean isSingleton = calleeContainingClass.getKind().isSingleton();
|
||||
@@ -2543,7 +2560,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
return StackValue.local(0, typeMapper.mapType(calleeContainingClass));
|
||||
}
|
||||
else if (isEnumEntry(calleeContainingClass)) {
|
||||
return StackValue.enumEntry(calleeContainingClass, typeMapper);
|
||||
if (!isInInnerClassConstructorContext(calleeContainingClass)) {
|
||||
return StackValue.enumEntry(calleeContainingClass, typeMapper);
|
||||
}
|
||||
// else fall-through
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassInEnumEntryClass.kt")
|
||||
public void testInnerClassInEnumEntryClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerClassInEnumEntryClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerWithExistingClassObject.kt")
|
||||
public void testInnerWithExistingClassObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||
|
||||
@@ -7811,6 +7811,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
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")
|
||||
public void testInnerWithExistingClassObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||
|
||||
@@ -7811,6 +7811,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
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")
|
||||
public void testInnerWithExistingClassObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||
|
||||
@@ -8609,6 +8609,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
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")
|
||||
public void testInnerWithExistingClassObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/enum/innerWithExistingClassObject.kt");
|
||||
|
||||
Reference in New Issue
Block a user