FIR2IR: Fix exception when local class used before declaration

This commit is contained in:
Denis.Zharkov
2021-10-22 16:49:02 +03:00
parent 0bdea4f20a
commit 2a8eacd4ba
11 changed files with 59 additions and 3 deletions
@@ -168,7 +168,7 @@ class Fir2IrClassifierStorage(
}
}
private fun createIrClass(klass: FirClass, parent: IrDeclarationParent? = null): IrClass {
private fun createLocalIrClass(klass: FirClass, parent: IrDeclarationParent? = null): IrClass {
// NB: klass can be either FirRegularClass or FirAnonymousObject
if (klass is FirAnonymousObject) {
return createIrAnonymousObject(klass, irParent = parent)
@@ -434,7 +434,7 @@ class Fir2IrClassifierStorage(
val firClass = firClassSymbol.fir
getCachedIrClass(firClass)?.let { return it.symbol }
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.Local) {
return createIrClass(firClass).symbol
return createLocalIrClass(firClass).symbol
}
val signature = signatureComposer.composeSignature(firClass)!!
symbolTable.referenceClassIfAny(signature)?.let { irClassSymbol ->
@@ -221,7 +221,13 @@ class Fir2IrConverter(
}
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
val irClass = classifierStorage.registerIrClass(regularClass, parent)
val irClass =
// Local classes might be referenced before they declared (see usages of Fir2IrClassifierStorage.createLocalIrClass)
// So, we only need to set its parent properly
classifierStorage.getCachedIrClass(regularClass)?.apply {
this.parent = parent
}
?: classifierStorage.registerIrClass(regularClass, parent)
regularClass.declarations.forEach {
if (it is FirRegularClass) {
registerClassAndNestedClasses(it, irClass)
@@ -26508,6 +26508,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@Test
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@Test
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
@@ -0,0 +1,6 @@
fun box(): String {
return object {
val a = A("OK")
inner class A(val ok: String)
}.a.ok
}
@@ -26370,6 +26370,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@Test
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@Test
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
@@ -26508,6 +26508,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@Test
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@Test
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
@@ -22277,6 +22277,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localDataClass.kt");
@@ -17261,6 +17261,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localDataClass.kt");
@@ -16667,6 +16667,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localDataClass.kt");
@@ -15963,6 +15963,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localDataClass.kt");
@@ -18704,6 +18704,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/localClasses/localClassInParameterInitializer.kt");
}
@Test
@TestMetadata("localClassUsedBeforeDeclaration.kt")
public void testLocalClassUsedBeforeDeclaration() throws Exception {
runTest("compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt");
}
@Test
@TestMetadata("localDataClass.kt")
public void testLocalDataClass() throws Exception {