From e4b314c26c6d35211faaa7fb650faf89cf81d1e6 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Mon, 16 Jul 2018 17:54:29 +0300 Subject: [PATCH] Fix inlining of `invoke` operator [#KT-25474] * add test --- .../js/test/semantics/BoxJsTestGenerated.java | 5 ++++ .../test/semantics/IrBoxJsTestGenerated.java | 5 ++++ .../callTranslator/CallTranslator.kt | 18 ++++++------ .../testData/box/inline/invokeOnField.kt | 29 +++++++++++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 js/js.translator/testData/box/inline/invokeOnField.kt diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 29a2ae80d7e..0dccde657ac 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -3930,6 +3930,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/inline/innerOuterThis.kt"); } + @TestMetadata("invokeOnField.kt") + public void testInvokeOnField() throws Exception { + runTest("js/js.translator/testData/box/inline/invokeOnField.kt"); + } + @TestMetadata("iteratorOnInlineFunctionResult.kt") public void testIteratorOnInlineFunctionResult() throws Exception { runTest("js/js.translator/testData/box/inline/iteratorOnInlineFunctionResult.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java index 4d7b0515ba0..4b3a416664e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java @@ -3930,6 +3930,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/inline/innerOuterThis.kt"); } + @TestMetadata("invokeOnField.kt") + public void testInvokeOnField() throws Exception { + runTest("js/js.translator/testData/box/inline/invokeOnField.kt"); + } + @TestMetadata("iteratorOnInlineFunctionResult.kt") public void testIteratorOnInlineFunctionResult() throws Exception { runTest("js/js.translator/testData/box/inline/iteratorOnInlineFunctionResult.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt index 15c4bd7acd2..311cd741ace 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/CallTranslator.kt @@ -109,22 +109,22 @@ private fun translateCall( if (resolvedCall is VariableAsFunctionResolvedCall) { assert(explicitReceivers.extensionReceiver == null) { "VariableAsFunctionResolvedCall must have one receiver" } val variableCall = resolvedCall.variableCall + val isFunctionType = variableCall.resultingDescriptor.type.isFunctionTypeOrSubtype + val inlineCall = if (isFunctionType) variableCall else resolvedCall - return if (variableCall.expectedReceivers()) { + val newExplicitReceivers = if (variableCall.expectedReceivers()) { val newReceiver = CallTranslator.translateGet(context, variableCall, explicitReceivers.extensionOrDispatchReceiver) - translateFunctionCall(context, resolvedCall.functionCall, resolvedCall.variableCall, ExplicitReceivers(newReceiver)) + ExplicitReceivers(newReceiver) } else { val dispatchReceiver = CallTranslator.translateGet(context, variableCall, null) - val isFunctionType = resolvedCall.variableCall.resultingDescriptor.type.isFunctionTypeOrSubtype - val inlineCall = if (isFunctionType) resolvedCall.variableCall else resolvedCall if (explicitReceivers.extensionOrDispatchReceiver == null) { - translateFunctionCall(context, resolvedCall.functionCall, inlineCall, ExplicitReceivers(dispatchReceiver)) - } - else { - translateFunctionCall(context, resolvedCall.functionCall, inlineCall, - ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver)) + ExplicitReceivers(dispatchReceiver) + } else { + ExplicitReceivers(dispatchReceiver, explicitReceivers.extensionOrDispatchReceiver) } } + + return translateFunctionCall(context, resolvedCall.functionCall, inlineCall, newExplicitReceivers) } val call = resolvedCall.call diff --git a/js/js.translator/testData/box/inline/invokeOnField.kt b/js/js.translator/testData/box/inline/invokeOnField.kt new file mode 100644 index 00000000000..c5c81eff845 --- /dev/null +++ b/js/js.translator/testData/box/inline/invokeOnField.kt @@ -0,0 +1,29 @@ +// EXPECTED_REACHABLE_NODES: 1189 +// CHECK_CONTAINS_NO_CALLS: testDispatch +// CHECK_CONTAINS_NO_CALLS: testExtension +class Bar { + inline operator fun invoke(f: () -> String) { f() } +} + +class Baz +inline operator fun Baz.invoke(f: () -> String) { f() } + +class Foo { + val bar = Bar() + val baz = Baz() +} + +fun testDispatch(foo: Foo): String { + foo.bar { return "O" } + return "FailDispatch;" +} + +fun testExtension(foo: Foo): String { + foo.baz { return "K" } + return "FailExtension;" +} + +fun box(): String { + val f = Foo() + return testDispatch(f) + testExtension(f) +} \ No newline at end of file