From 07cb3a5ff8089e7774a4bd1c3203d736e9a6801f Mon Sep 17 00:00:00 2001 From: pyos Date: Wed, 7 Jul 2021 17:58:17 +0200 Subject: [PATCH] JVM: do not reify methods of objects in lambdas All type parameters used in them are not from the inline function anyway. --- .../codegen/inline/AnonymousObjectTransformer.kt | 12 ++++++------ .../kotlin/codegen/inline/InliningContext.kt | 13 +++++++++++-- .../kotlin/codegen/inline/MethodInliner.kt | 10 ++-------- .../FirBlackBoxInlineCodegenTestGenerated.java | 6 ++++++ .../codegen/boxInline/reified/nameClash.kt | 16 ++++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 6 ++++++ ...leKotlinAgainstInlineKotlinTestGenerated.java | 6 ++++++ .../IrBlackBoxInlineCodegenTestGenerated.java | 6 ++++++ ...leKotlinAgainstInlineKotlinTestGenerated.java | 6 ++++++ .../JvmIrAgainstOldBoxInlineTestGenerated.java | 6 ++++++ .../JvmOldAgainstIrBoxInlineTestGenerated.java | 6 ++++++ .../IrJsCodegenInlineES6TestGenerated.java | 5 +++++ .../IrJsCodegenInlineTestGenerated.java | 5 +++++ .../semantics/JsCodegenInlineTestGenerated.java | 5 +++++ 14 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/reified/nameClash.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index f00f5e9df21..2ccc52d9891 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -295,7 +295,6 @@ class AnonymousObjectTransformer( capturedBuilder: ParametersBuilder, isConstructor: Boolean ): InlineResult { - val typeParametersToReify = inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode) val parameters = if (isConstructor) capturedBuilder.buildParameters() else getMethodParametersWithCaptured(capturedBuilder, sourceNode) @@ -304,7 +303,10 @@ class AnonymousObjectTransformer( transformationInfo.capturedLambdasToInline, parentRemapper, isConstructor ) - val inliner = MethodInliner( + val reifiedTypeParametersUsages = if (inliningContext.shouldReifyTypeParametersInObjects) + inliningContext.root.inlineMethodReifier.reifyInstructions(sourceNode) + else null + val result = MethodInliner( sourceNode, parameters, inliningContext.subInline(transformationInfo.nameGenerator), @@ -319,10 +321,8 @@ class AnonymousObjectTransformer( inliningContext.callSiteInfo.file, inliningContext.callSiteInfo.lineNumber ), null - ) - - val result = inliner.doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf()) - result.reifiedTypeParametersUsages.mergeAll(typeParametersToReify) + ).doInline(deferringVisitor, LocalVarRemapper(parameters, 0), false, mapOf()) + reifiedTypeParametersUsages?.let(result.reifiedTypeParametersUsages::mergeAll) deferringVisitor.visitMaxs(-1, -1) return result } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt index 1123336f413..9480f6631a6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InliningContext.kt @@ -44,8 +44,16 @@ open class InliningContext( val lambdaInfo: LambdaInfo?, val classRegeneration: Boolean ) { + val isInliningLambda + get() = lambdaInfo != null - val isInliningLambda = lambdaInfo != null + // Consider this arrangement: + // inline fun f(x: () -> Unit = { /* uses `T` in a local class */ }) = x() + // inline fun g() = f<...> { /* uses `V` in a local class */ } + // When inlining `f` into `g`, we need to reify the contents of the default for `x` (if it was used), but not the + // contents of the lambda passed as the argument in `g` as all reified type parameters used by the latter are not from `f`. + val shouldReifyTypeParametersInObjects: Boolean + get() = lambdaInfo == null || lambdaInfo is DefaultLambda var generateAssertField = false @@ -54,7 +62,8 @@ open class InliningContext( var isContinuation: Boolean = false - val isRoot: Boolean = parent == null + val isRoot: Boolean + get() = parent == null val root: RootInliningContext get() = if (isRoot) this as RootInliningContext else parent!!.root diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index e8d6409f699..147e0f95bbd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -318,14 +318,8 @@ class MethodInliner( super.visitMethodInsn(opcode, owner, name, desc, itf) } } else if (ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) { - // Consider this arrangement: - // inline fun f(x: () -> Unit = { /* uses `T` in a local class */ }) = x() - // inline fun g() = f<...> { /* uses `V` in a local class */ } - // When inlining `f` into `g`, we need to erase class reification markers from `f` and the default lambda - // (they will be recreated by `handleAnonymousObjectRegeneration` above if `T` is instantiated with another - // reified type parameter), but not from the lambda passed to `f` in `g` (as reified type parameters inside - // it do not belong to `f`, thus we cannot substitute them yet). - if (inliningContext.isInliningLambda && inliningContext.lambdaInfo !is DefaultLambda) { + // If objects are reified, the marker will be recreated by `handleAnonymousObjectRegeneration` above. + if (!inliningContext.shouldReifyTypeParametersInObjects) { super.visitMethodInsn(opcode, owner, name, desc, itf) } } else { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java index b567d70d628..39db1bcfe5b 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java @@ -3822,6 +3822,12 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/compiler/testData/codegen/boxInline/reified/nameClash.kt b/compiler/testData/codegen/boxInline/reified/nameClash.kt new file mode 100644 index 00000000000..b5152c1e07a --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/nameClash.kt @@ -0,0 +1,16 @@ +// FILE: 1.kt +package test + +inline fun f(x: () -> String) = x() + +inline fun g() = f { + val x = { T::class.simpleName } + x()!! +} + +// FILE: 2.kt +import test.* + +class OK + +fun box() = g() diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java index d8d9a1fe3f6..baa56d1e4d4 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -3822,6 +3822,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index f12831ecaed..33f3363c695 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -3822,6 +3822,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java index bed351acab3..8ef58d64cd7 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java @@ -3822,6 +3822,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 1cd27d2c6f3..e63da2b8cd0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -3822,6 +3822,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java index d75f4e6903e..8db6ee4da49 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -3822,6 +3822,12 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java index bc5dc17bfa1..3b4aedaea55 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -3822,6 +3822,12 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @Test + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @Test @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java index 7d941344e53..8c4aefec3af 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenInlineES6TestGenerated.java @@ -3085,6 +3085,11 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java index 944d1474d02..fb89be60773 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenInlineTestGenerated.java @@ -3085,6 +3085,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java index f2773db60dc..19fb085aaf8 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenInlineTestGenerated.java @@ -3085,6 +3085,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest { runTest("compiler/testData/codegen/boxInline/reified/kt9637_2.kt"); } + @TestMetadata("nameClash.kt") + public void testNameClash() throws Exception { + runTest("compiler/testData/codegen/boxInline/reified/nameClash.kt"); + } + @TestMetadata("nonCapturingObjectInLambda.kt") public void testNonCapturingObjectInLambda() throws Exception { runTest("compiler/testData/codegen/boxInline/reified/nonCapturingObjectInLambda.kt");