diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 920a680ab2f..3847803ec6a 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -4358,6 +4358,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt"); diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 645acb119ce..a325c088897 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -570,12 +570,18 @@ class LocalDeclarationsLowering( private fun generateNameForLiftedDeclaration( declaration: IrDeclaration, newOwner: IrDeclarationParent - ): Name = - Name.identifier( - declaration.parentsWithSelf - .takeWhile { it != newOwner } - .toList().reversed().joinToString(separator = "$") { suggestLocalName(it as IrDeclarationWithName) } - ) + ): Name { + val parents = declaration.parentsWithSelf.takeWhile { it != newOwner }.toList().reversed() + val nameFromParents = parents.joinToString(separator = "$") { suggestLocalName(it as IrDeclarationWithName) } + // Local functions declared in anonymous initializers have classes as their parents. + // Such anonymous initializers, however, are inlined into the constructors delegating to super class constructor. + // There can be local functions declared in local function in init blocks (and further), + // but such functions would have proper "safe" names (outerLocalFun1$outerLocalFun2$...$localFun). + return if (parents.size == 1 && declaration.parent is IrClass) + Name.identifier("_init_\$$nameFromParents") + else + Name.identifier(nameFromParents) + } private fun createLiftedDeclaration(localFunctionContext: LocalFunctionContext) { val oldDeclaration = localFunctionContext.declaration diff --git a/compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt b/compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt new file mode 100644 index 00000000000..236932f6625 --- /dev/null +++ b/compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt @@ -0,0 +1,28 @@ +// IGNORE_BACKEND_FIR: JVM_IR + +lateinit var result1: String +lateinit var result2: String + +class Test(val x: String) { + fun test(a: String) { + if (result1 != a) throw AssertionError("result1: $result1") + result2 = a + } + + init { + fun test() { + fun test1() { + result1 = x + } + test1() + } + test() + } +} + +fun box(): String { + val t = Test("OK") + t.test("OK") + + return result2 +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt b/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt new file mode 100644 index 00000000000..18ed2a6a750 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt @@ -0,0 +1,23 @@ +class C() { + constructor(x: Int): this() { + fun test() { + fun test() {} + } + } + + constructor(y: String): this() { + fun test() { + fun test() {} + } + } + + fun test() { + fun test() {} + } + + init { + fun test() { + fun test() {} + } + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.txt b/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.txt new file mode 100644 index 00000000000..d6d15ab6710 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.txt @@ -0,0 +1,87 @@ +@kotlin.Metadata +final class C$1$1 { + public final static field INSTANCE: C$1$1 + inner (anonymous) class C$1 + inner (anonymous) class C$1$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +final class C$1 { + public final static field INSTANCE: C$1 + inner (anonymous) class C$1 + inner (anonymous) class C$1$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +final class C$2$1 { + public final static field INSTANCE: C$2$1 + inner (anonymous) class C$2 + inner (anonymous) class C$2$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +final class C$2 { + public final static field INSTANCE: C$2 + inner (anonymous) class C$2 + inner (anonymous) class C$2$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +final class C$3$1 { + public final static field INSTANCE: C$3$1 + inner (anonymous) class C$3 + inner (anonymous) class C$3$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +final class C$3 { + public final static field INSTANCE: C$3 + inner (anonymous) class C$3 + inner (anonymous) class C$3$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +final class C$test$1 { + public final static field INSTANCE: C$test$1 + inner (anonymous) class C$test$1 + static method (): void + method (): void + public synthetic bridge method invoke(): java.lang.Object + public final method invoke(): void +} + +@kotlin.Metadata +public final class C { + inner (anonymous) class C$1 + inner (anonymous) class C$2 + inner (anonymous) class C$3 + inner (anonymous) class C$test$1 + public method (): void + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public method (p0: int): void + public final method test(): void +} diff --git a/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock_ir.txt b/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock_ir.txt new file mode 100644 index 00000000000..04652eed297 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock_ir.txt @@ -0,0 +1,14 @@ +@kotlin.Metadata +public final class C { + public method (): void + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public method (p0: int): void + private final static method _init_$test-0$test(): void + private final static method _init_$test-0(): void + private final static method _init_$test-2$test-1(): void + private final static method _init_$test-2(): void + private final static method _init_$test-5(): void + private final static method test$test-3(): void + public final method test(): void + private final static method test-5$test-4(): void +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index c715000b72c..37e07672a7d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4378,6 +4378,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index ceb4fa0f839..4675180bf19 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -99,6 +99,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/lateInitNotNull.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt"); + } + @TestMetadata("noCollectionStubMethodsInInterface.kt") public void testNoCollectionStubMethodsInInterface() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 535eb66a749..bb2b2a184b2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -4378,6 +4378,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 0078395e61a..6cade59e648 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -4358,6 +4358,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index 3b58390a514..64c33c833c7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -99,6 +99,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/lateInitNotNull.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt"); + } + @TestMetadata("noCollectionStubMethodsInInterface.kt") public void testNoCollectionStubMethodsInInterface() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/noCollectionStubMethodsInInterface.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 53ed9829264..ba8da39592c 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -3608,6 +3608,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 8088b77cb41..004d0bccc91 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -3608,6 +3608,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index d9a44fcdfbd..ba8b105ef31 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -3608,6 +3608,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/closures/localFunctionInFunction.kt"); } + @TestMetadata("localFunctionInInitBlock.kt") + public void testLocalFunctionInInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/closures/localFunctionInInitBlock.kt"); + } + @TestMetadata("localFunctionInInitializer.kt") public void testLocalFunctionInInitializer() throws Exception { runTest("compiler/testData/codegen/box/closures/localFunctionInInitializer.kt");