From 6b65a2ea7de5662399ef6fc876663f05cd8a7575 Mon Sep 17 00:00:00 2001 From: pyos Date: Mon, 31 Aug 2020 13:12:58 +0200 Subject: [PATCH] JVM_IR: move classes out of lambdas inlined into initializers Fixes KT-41465 --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 ++++ .../jvm/lower/JvmLocalClassPopupLowering.kt | 30 +++++++++++++++---- .../inlineIntoTwoConstructors.kt | 10 +++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++++ .../LightAnalysisModeTestGenerated.java | 5 ++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++++ .../IrJsCodegenBoxES6TestGenerated.java | 5 ++++ .../IrJsCodegenBoxTestGenerated.java | 5 ++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++++ 9 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.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 f961ea15ecb..bdf17724e5b 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 @@ -28935,6 +28935,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLocalClassPopupLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLocalClassPopupLowering.kt index fbe06f50e84..afadc083cc6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLocalClassPopupLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmLocalClassPopupLowering.kt @@ -9,15 +9,29 @@ import org.jetbrains.kotlin.backend.common.ScopeWithIr import org.jetbrains.kotlin.backend.common.lower.LocalClassPopupLowering import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.primaryConstructor import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull class JvmLocalClassPopupLowering(context: JvmBackendContext) : LocalClassPopupLowering(context) { + private val inlineLambdaToScope = mutableMapOf() + + override fun lower(irFile: IrFile) { + irFile.accept(object : IrInlineReferenceLocator(context as JvmBackendContext) { + override fun visitInlineLambda( + argument: IrFunctionReference, callee: IrFunction, parameter: IrValueParameter, scope: IrDeclaration + ) { + inlineLambdaToScope[argument.symbol.owner] = scope + } + }, null) + super.lower(irFile) + inlineLambdaToScope.clear() + } + // On JVM, we only pop up local classes in field initializers and anonymous init blocks, so that InitializersLowering would not copy // them to each constructor. (Moving all local classes is not possible because of cases where they use reified type parameters, // or capture crossinline lambdas.) @@ -31,9 +45,13 @@ class JvmLocalClassPopupLowering(context: JvmBackendContext) : LocalClassPopupLo klass.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE if (!isLocal) return false - val container = when (val element = currentScope?.irElement) { - is IrAnonymousInitializer -> element.parentAsClass.takeUnless { element.isStatic } - is IrField -> element.parentAsClass.takeUnless { element.isStatic } + var parent = currentScope?.irElement + while (parent is IrFunction) { + parent = inlineLambdaToScope[parent] ?: break + } + val container = when (parent) { + is IrAnonymousInitializer -> parent.parentAsClass.takeUnless { parent.isStatic } + is IrField -> parent.parentAsClass.takeUnless { parent.isStatic } else -> null } ?: return false diff --git a/compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt b/compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt new file mode 100644 index 00000000000..c76a5666763 --- /dev/null +++ b/compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt @@ -0,0 +1,10 @@ +inline fun myRun(x: () -> String) = x() + +class C { + val x = myRun { { "OK" }() } + + constructor(y: Int) + constructor(y: String) +} + +fun box(): String = C("").x diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index fd7b8ebba57..8b85be2908a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -30531,6 +30531,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index f2493756a6f..7f3ffd31e1f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -28165,6 +28165,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 4bf973852b8..3842e671f58 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -28935,6 +28935,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.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 8167d57cfa2..6188fc4b272 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 @@ -23521,6 +23521,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.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 fef39e6b3dc..469147a0473 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 @@ -23521,6 +23521,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.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 c9710cb4367..000d0c4d7fe 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 @@ -23536,6 +23536,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/secondaryConstructors/generics.kt"); } + @TestMetadata("inlineIntoTwoConstructors.kt") + public void testInlineIntoTwoConstructors() throws Exception { + runTest("compiler/testData/codegen/box/secondaryConstructors/inlineIntoTwoConstructors.kt"); + } + @TestMetadata("innerClasses.kt") public void testInnerClasses() throws Exception { runTest("compiler/testData/codegen/box/secondaryConstructors/innerClasses.kt");