diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt index 0c7515609c3..6ab3ca69855 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/MethodsOfAnyCallsTransformer.kt @@ -64,20 +64,17 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform } private fun shouldReplaceToStringWithRuntimeCall(call: IrFunctionAccessExpression): Boolean { - // TODO: (KOTLIN-CR-2079) - // - User defined extension functions Any?.toString() call can be lost during lowering. - // - Use direct method call for dynamic types??? - // - Define Any?.toString() in runtime library and stop intrinsicifying extensions - - if (call.valueArgumentsCount > 0) + val function = call.symbol.owner + if (function.valueParameters.size != 0 && function.name.asString() != "toString" ) return false - val receiverParameterType = with(call.symbol.owner) { - dispatchReceiverParameter ?: extensionReceiverParameter - }?.type ?: return false + if (function.extensionReceiverParameter != null) + return false + + val receiverParameterType = function.dispatchReceiverParameter?.type ?: return false return receiverParameterType.run { - isArray() || isAny() || isNullable() || this is IrDynamicType || isString() + isArray() || isAny() || this is IrDynamicType || isString() } } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 4f63c9f7117..e71910b80c6 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -6805,6 +6805,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { public void testTaggedArrayCopy() throws Exception { runTest("js/js.translator/testData/box/regression/typeChecks/taggedArrayCopy.kt"); } + + @TestMetadata("toStringExtension.kt") + public void testToStringExtension() throws Exception { + runTest("js/js.translator/testData/box/regression/typeChecks/toStringExtension.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 f0420b053d5..93222c42e26 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 @@ -6840,6 +6840,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { public void testTaggedArrayCopy() throws Exception { runTest("js/js.translator/testData/box/regression/typeChecks/taggedArrayCopy.kt"); } + + @TestMetadata("toStringExtension.kt") + public void testToStringExtension() throws Exception { + runTest("js/js.translator/testData/box/regression/typeChecks/toStringExtension.kt"); + } } } diff --git a/js/js.translator/testData/box/regression/typeChecks/toStringExtension.kt b/js/js.translator/testData/box/regression/typeChecks/toStringExtension.kt new file mode 100644 index 00000000000..0622c6fff0a --- /dev/null +++ b/js/js.translator/testData/box/regression/typeChecks/toStringExtension.kt @@ -0,0 +1,9 @@ +// EXPECTED_REACHABLE_NODES: 1281 + +package foo + +class A + +fun A?.toString() = "OK" + +fun box() = (null as A?).toString() \ No newline at end of file