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:
Dmitry Petrov
2017-09-08 12:35:25 +03:00
parent 26b2f59b86
commit 66ece54b25
6 changed files with 65 additions and 1 deletions
@@ -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
@@ -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");