diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index 9211bd74c79..0ecd509e170 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -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 -> diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index a4845526f17..aa601a45f43 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -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) diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 23ffc9417b4..fb82ea078a0 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt b/compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt new file mode 100644 index 00000000000..0e5a5c087fd --- /dev/null +++ b/compiler/testData/codegen/box/localClasses/localClassUsedBeforeDeclaration.kt @@ -0,0 +1,6 @@ +fun box(): String { + return object { + val a = A("OK") + inner class A(val ok: String) + }.a.ok +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 4b7f5bfbd03..3e3b46fd2a1 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 9697d31f2e3..2cecb82b66c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 1d375a4eeb8..35675151d90 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index f563c3ff750..f54936d6acb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index e5d88363fa6..23208758d04 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index e3fa2541dd4..5ce373afe5d 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -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"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testNew/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testNew/JsCodegenBoxTestGenerated.java index c176e1f5875..c68f51024eb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testNew/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testNew/JsCodegenBoxTestGenerated.java @@ -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 {