From ea980622418e5641be838064234b71d58911658e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Wed, 19 Aug 2020 18:42:47 +0200 Subject: [PATCH] JVM IR: Fix compilation of inline functions in anonymous objects... ...in class members. The corresponding classes end up nested in the class initializer of the surrounding class and we need to take this into account when creating instances of ClassCodegen. This fixes KT-40332 on the JVM IR backend. --- .../codegen/ir/FirBlackBoxCodegenTestGenerated.java | 5 +++++ .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 11 ++++++++++- compiler/testData/codegen/box/classes/kt40332.kt | 11 +++++++++++ .../kotlin/codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../codegen/LightAnalysisModeTestGenerated.java | 5 +++++ .../codegen/ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ .../es6/semantics/IrJsCodegenBoxES6TestGenerated.java | 5 +++++ .../ir/semantics/IrJsCodegenBoxTestGenerated.java | 5 +++++ .../js/test/semantics/JsCodegenBoxTestGenerated.java | 5 +++++ 9 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/classes/kt40332.kt 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 cb69accca52..2bd5c9f58d1 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 @@ -4025,6 +4025,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/classes/kt3546.kt"); } + @TestMetadata("kt40332.kt") + public void testKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + @TestMetadata("kt454.kt") public void testKt454() throws Exception { runTest("compiler/testData/codegen/box/classes/kt454.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 6d892382805..733cc0fc7a9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -226,7 +226,16 @@ abstract class ClassCodegen protected constructor( fun getOrCreate( irClass: IrClass, context: JvmBackendContext, - parentFunction: IrFunction? = null, + // The `parentFunction` is only set for classes nested inside of functions. This is usually safe, since there is no + // way to refer to (inline) members of such a class from outside of the function unless the function in question is + // itself declared as inline. In that case, the function will be compiled before we can refer to the nested class. + // + // The one exception to this rule are anonymous objects defined as members of a class. These are nested inside of the + // class initializer, but can be referred to from anywhere within the scope of the class. That's why we have to ensure + // that all references to classes inside of have a non-null `parentFunction`. + parentFunction: IrFunction? = irClass.parent.safeAs()?.takeIf { + it.origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER + }, ): ClassCodegen = context.classCodegens.getOrPut(irClass) { context.createCodegen(irClass, context, parentFunction) ?: DescriptorBasedClassCodegen(irClass, context, parentFunction) diff --git a/compiler/testData/codegen/box/classes/kt40332.kt b/compiler/testData/codegen/box/classes/kt40332.kt new file mode 100644 index 00000000000..d1c4ac75ebb --- /dev/null +++ b/compiler/testData/codegen/box/classes/kt40332.kt @@ -0,0 +1,11 @@ +// IGNORE_BACKEND: JVM + +object A { + private val s = object { + inline operator fun invoke(): String = "OK" + } + + fun value() = s() +} + +fun box(): String = A.value() diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index cf348a99c7a..aff052eb00a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4045,6 +4045,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/classes/kt3546.kt"); } + @TestMetadata("kt40332.kt") + public void testKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + @TestMetadata("kt454.kt") public void testKt454() throws Exception { runTest("compiler/testData/codegen/box/classes/kt454.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b90283acb3e..8ee7e1ae5fb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -3642,6 +3642,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class Classes extends AbstractLightAnalysisModeTest { + @TestMetadata("kt40332.kt") + public void ignoreKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 05636c326d5..c2e32202077 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -4025,6 +4025,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/classes/kt3546.kt"); } + @TestMetadata("kt40332.kt") + public void testKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + @TestMetadata("kt454.kt") public void testKt454() throws Exception { runTest("compiler/testData/codegen/box/classes/kt454.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 cbd580f6750..cea8f086238 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 @@ -3205,6 +3205,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/classes/kt3546.kt"); } + @TestMetadata("kt40332.kt") + public void testKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + @TestMetadata("kt454.kt") public void testKt454() throws Exception { runTest("compiler/testData/codegen/box/classes/kt454.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 9f6b997105b..d3c59cdb49c 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 @@ -3205,6 +3205,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/classes/kt3546.kt"); } + @TestMetadata("kt40332.kt") + public void testKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + @TestMetadata("kt454.kt") public void testKt454() throws Exception { runTest("compiler/testData/codegen/box/classes/kt454.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 8860b58d810..c5ea5ad2ad1 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 @@ -3205,6 +3205,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/classes/kt3546.kt"); } + @TestMetadata("kt40332.kt") + public void testKt40332() throws Exception { + runTest("compiler/testData/codegen/box/classes/kt40332.kt"); + } + @TestMetadata("kt454.kt") public void testKt454() throws Exception { runTest("compiler/testData/codegen/box/classes/kt454.kt");