From 07bb7ef4d3c6dc651aa71fd1faf34cb8a7a9a5f5 Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Mon, 16 Jan 2017 16:24:06 +0300 Subject: [PATCH] JS: extension lambdas translated same as local lambdas (KT-13312 fixed) --- .../codegen/box/extensionFunctions/kt13312.kt | 23 ++++++++++ .../codegen/box/extensionFunctions/kt3646.kt | 3 -- .../invoke/castFunctionToExtension.kt | 3 -- .../box/functions/localFunctions/kt4989.kt | 3 -- .../codegen/box/operatorConventions/kt4987.kt | 3 -- .../functions/functionFromStdlib.kt | 3 -- .../boxInline/callableReference/classLevel.kt | 2 - .../callableReference/classLevel2.kt | 2 - .../callableReference/topLevelExtension.kt | 2 - .../extensionFunctions/kt13312.txt | 13 ++++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ ...LightAnalysisModeCodegenTestGenerated.java | 6 +++ .../kotlin/js/inline/ExpressionDecomposer.kt | 29 +++++++----- .../kotlin/js/inline/FunctionInlineMutator.kt | 3 +- .../kotlin/js/inline/FunctionReader.kt | 9 +--- .../js/inline/clean/FunctionPostProcessor.kt | 4 +- ...ination.kt => RedundantCallElimination.kt} | 27 ++++++----- js/js.libraries/src/core/coroutines.kt | 4 +- .../src/js/callableReferenceUtils.js | 14 ------ ...CallableReferenceInlineTestsGenerated.java | 24 ++-------- .../semantics/JsCodegenBoxTestGenerated.java | 46 +++++-------------- .../callTranslator/FunctionCallCases.kt | 24 ++-------- .../callTranslator/VariableCallCases.kt | 2 +- .../kotlin/js/translate/context/Namer.java | 16 ------- .../expression/FunctionTranslator.kt | 3 +- .../reference/CallableReferenceTranslator.kt | 10 +--- .../reference/VariableAccessTranslator.java | 6 +-- .../kotlin/js/translate/utils/inlineUtils.kt | 4 +- .../box/native/passExtLambdaFromNative.js | 2 +- .../box/native/passExtLambdaToNative.js | 2 +- .../box/native/passMemberOrExtToNative.js | 2 +- 32 files changed, 123 insertions(+), 183 deletions(-) create mode 100644 compiler/testData/codegen/box/extensionFunctions/kt13312.kt create mode 100644 compiler/testData/codegen/light-analysis/extensionFunctions/kt13312.txt rename js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/{RedundantBindElimination.kt => RedundantCallElimination.kt} (58%) diff --git a/compiler/testData/codegen/box/extensionFunctions/kt13312.kt b/compiler/testData/codegen/box/extensionFunctions/kt13312.kt new file mode 100644 index 00000000000..097fa273eb5 --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/kt13312.kt @@ -0,0 +1,23 @@ +fun test1(f: (Int) -> Int) = f(1) + +fun test2(f: Int.() -> Int) = 2.f() + +class A(val foo: Int.() -> Int) + +fun box(): String { + val a: (Int) -> Int = { it } + val b: Int.() -> Int = { this } + + if (test1(a) != 1) return "fail 1a" + if (test1(b) != 1) return "fail 1b" + if (test2(a) != 2) return "fail 2a" + if (test2(b) != 2) return "fail 2b" + + val x = A({ this }) + + if (x.foo(3) != 3) return "fail 3" + if (with(x) { foo(4) } != 4) return "fail 4" + if (with(x) { 5.foo() } != 5) return "fail 5" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/extensionFunctions/kt3646.kt b/compiler/testData/codegen/box/extensionFunctions/kt3646.kt index c1ddef88264..c3f758cf9a5 100644 --- a/compiler/testData/codegen/box/extensionFunctions/kt3646.kt +++ b/compiler/testData/codegen/box/extensionFunctions/kt3646.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - fun test(cl: Int.() -> Int):Int = 11.cl() class Foo { diff --git a/compiler/testData/codegen/box/functions/invoke/castFunctionToExtension.kt b/compiler/testData/codegen/box/functions/invoke/castFunctionToExtension.kt index aa27b96d877..cb638d7b24f 100644 --- a/compiler/testData/codegen/box/functions/invoke/castFunctionToExtension.kt +++ b/compiler/testData/codegen/box/functions/invoke/castFunctionToExtension.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - fun box(): String { val f = fun (s: String): String = s val g = f as String.() -> String diff --git a/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt b/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt index d42b8a0b6b0..e4cee2aa56f 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - class It(val id: String) fun box(): String { diff --git a/compiler/testData/codegen/box/operatorConventions/kt4987.kt b/compiler/testData/codegen/box/operatorConventions/kt4987.kt index ece3a7822ba..ed28874dbbc 100644 --- a/compiler/testData/codegen/box/operatorConventions/kt4987.kt +++ b/compiler/testData/codegen/box/operatorConventions/kt4987.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - fun box(): String { operator fun Int?.inc() = (this ?: 0) + 1 var counter: Int? = null diff --git a/compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt b/compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt index a6200e2c7ef..231c44f208d 100644 --- a/compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt +++ b/compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt @@ -1,6 +1,3 @@ -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS - // WITH_REFLECT fun doStuff(fn: String.() -> String) = "ok".fn() diff --git a/compiler/testData/codegen/boxInline/callableReference/classLevel.kt b/compiler/testData/codegen/boxInline/callableReference/classLevel.kt index 9444000c34c..384931b1398 100644 --- a/compiler/testData/codegen/boxInline/callableReference/classLevel.kt +++ b/compiler/testData/codegen/boxInline/callableReference/classLevel.kt @@ -1,5 +1,3 @@ -// Enable when using lambdas as extension lambdas is supported (KT-13312) -// IGNORE_BACKEND: JS // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/callableReference/classLevel2.kt b/compiler/testData/codegen/boxInline/callableReference/classLevel2.kt index 5f90d337c73..893b834aed8 100644 --- a/compiler/testData/codegen/boxInline/callableReference/classLevel2.kt +++ b/compiler/testData/codegen/boxInline/callableReference/classLevel2.kt @@ -1,5 +1,3 @@ -// Enable when using lambdas as extension lambdas is supported (KT-13312) -// IGNORE_BACKEND: JS // FILE: 1.kt package test diff --git a/compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt b/compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt index f3fe5e147ca..eaabbf11261 100644 --- a/compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt +++ b/compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt @@ -1,5 +1,3 @@ -// Enable when using lambdas as extension lambdas is supported (KT-13312) -// IGNORE_BACKEND: JS // FILE: 1.kt package test diff --git a/compiler/testData/codegen/light-analysis/extensionFunctions/kt13312.txt b/compiler/testData/codegen/light-analysis/extensionFunctions/kt13312.txt new file mode 100644 index 00000000000..3d8ac2b0c22 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/extensionFunctions/kt13312.txt @@ -0,0 +1,13 @@ +@kotlin.Metadata +public final class A { + private final @org.jetbrains.annotations.NotNull field foo: kotlin.jvm.functions.Function1 + public method (@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void + public final @org.jetbrains.annotations.NotNull method getFoo(): kotlin.jvm.functions.Function1 +} + +@kotlin.Metadata +public final class Kt13312Kt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String + public final static method test1(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): int + public final static method test2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): int +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 1dd9aa5e3ae..75e58b26875 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -7142,6 +7142,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("kt13312.kt") + public void testKt13312() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt"); + doTest(fileName); + } + @TestMetadata("kt1776.kt") public void testKt1776() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index c68a921c727..327182960d9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -7142,6 +7142,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kt13312.kt") + public void testKt13312() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt"); + doTest(fileName); + } + @TestMetadata("kt1776.kt") public void testKt1776() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index 685c064dc7a..dcea0a3a246 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -7142,6 +7142,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } + @TestMetadata("kt13312.kt") + public void testKt13312() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt"); + doTest(fileName); + } + @TestMetadata("kt1776.kt") public void testKt1776() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt"); diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt index 9a957daff2b..23e0373729a 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt @@ -23,8 +23,8 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic import org.jetbrains.kotlin.js.inline.util.IdentitySet -import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.inline.util.rewriters.ContinueReplacingVisitor +import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.* import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.* @@ -288,8 +288,8 @@ internal class ExpressionDecomposer private constructor( private fun Callable.process() { qualifier = accept(qualifier) - val matchedIndices = arguments.indicesOfExtractable - if (!matchedIndices.hasNext()) return + var matchedIndices = arguments.indicesOfExtractable + if (matchedIndices.isEmpty()) return if (qualifier in containsNodeWithSideEffect) { val callee = qualifier as? JsNameRef @@ -307,20 +307,27 @@ internal class ExpressionDecomposer private constructor( else { if (receiver != null && applyBindIfNecessary) { val receiverTmp = receiver.extractToTemporary() - qualifier = JsAstUtils.invokeBind(receiverTmp, pureFqn(callee.ident, receiverTmp)) + val fqn = JsNameRef(callee.ident, receiverTmp).apply { + synthetic = true + callee.name?.let { sideEffects = it.sideEffects } + } + qualifier = fqn.extractToTemporary() + qualifier = Namer.getFunctionCallRef(qualifier) + arguments.add(0, receiverTmp) + matchedIndices = matchedIndices.map { it + 1 } + } + else { + qualifier = qualifier.extractToTemporary() } - qualifier = qualifier.extractToTemporary() } } processByIndices(arguments, matchedIndices) } - private fun processByIndices(elements: MutableList, matchedIndices: Iterator) { + private fun processByIndices(elements: MutableList, matchedIndices: List) { var prev = 0 - while (matchedIndices.hasNext()) { - val curr = matchedIndices.next() - + for (curr in matchedIndices) { for (i in prev..curr-1) { val arg = elements[i] if (arg !in containsNodeWithSideEffect) continue @@ -374,8 +381,8 @@ internal class ExpressionDecomposer private constructor( } } - private val List.indicesOfExtractable: Iterator - get() = indices.filter { get(it) in containsExtractable }.iterator() + private val List.indicesOfExtractable: List + get() = indices.filter { get(it) in containsExtractable } } /** diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt index cfed958b360..c85d6735088 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionInlineMutator.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.js.inline.clean.removeDefaultInitializers import org.jetbrains.kotlin.js.inline.context.InliningContext import org.jetbrains.kotlin.js.inline.util.* import org.jetbrains.kotlin.js.inline.util.rewriters.ReturnReplacingVisitor +import org.jetbrains.kotlin.js.translate.context.Namer class FunctionInlineMutator private constructor( @@ -77,7 +78,7 @@ private constructor( return when (qualifier) { is JsInvocation -> qualifier is JsNameRef -> { - val callee = if (qualifier.ident == "call") qualifier.qualifier else (qualifier.name?.staticRef as? JsExpression) + val callee = if (qualifier.ident == Namer.CALL_FUNCTION) qualifier.qualifier else (qualifier.name?.staticRef as? JsExpression) callee?.let { getInnerCall(it) } } else -> null diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index e9a89640c38..aa86e3a9faa 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -171,7 +171,6 @@ private fun JsFunction.markInlineArguments(descriptor: CallableDescriptor) { val params = descriptor.valueParameters val paramsJs = parameters val inlineFuns = IdentitySet() - val inlineExtensionFuns = IdentitySet() val offset = if (descriptor.isExtension) 1 else 0 for ((i, param) in params.withIndex()) { @@ -180,25 +179,21 @@ private fun JsFunction.markInlineArguments(descriptor: CallableDescriptor) { val type = param.type if (!type.isFunctionTypeOrSubtype) continue - val namesSet = if (type.isExtensionFunctionType) inlineExtensionFuns else inlineFuns - namesSet.add(paramsJs[i + offset].name) + inlineFuns.add(paramsJs[i + offset].name) } val visitor = object: JsVisitorWithContextImpl() { override fun endVisit(x: JsInvocation, ctx: JsContext<*>) { val qualifier: JsExpression? - val namesSet: Set if (isCallInvocation(x)) { qualifier = (x.qualifier as? JsNameRef)?.qualifier - namesSet = inlineExtensionFuns } else { qualifier = x.qualifier - namesSet = inlineFuns } (qualifier as? JsNameRef)?.name?.let { name -> - if (name in namesSet) { + if (name in inlineFuns) { x.inlineStrategy = InlineStrategy.IN_PLACE } } diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt index 7835f62aeac..c8cfdbc2d71 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/FunctionPostProcessor.kt @@ -18,14 +18,14 @@ package org.jetbrains.kotlin.js.inline.clean import org.jetbrains.kotlin.js.backend.ast.JsFunction -class FunctionPostProcessor(root: JsFunction) { +class FunctionPostProcessor(val root: JsFunction) { val optimizations = listOf( //{ TemporaryAssignmentElimination(root.body).apply() }, { RedundantLabelRemoval(root.body).apply() }, { WhileConditionFolding(root.body).apply() }, { DoWhileGuardElimination(root.body).apply() }, { TemporaryVariableElimination(root).apply() }, - { RedundantBindElimination(root.body).apply() }, + { RedundantCallElimination(root.body).apply() }, { IfStatementReduction(root.body).apply() }, { DeadCodeElimination(root.body).apply() }, { RedundantVariableDeclarationElimination(root.body).apply() }, diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantBindElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantCallElimination.kt similarity index 58% rename from js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantBindElimination.kt rename to js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantCallElimination.kt index 7b127fcbfb4..49953bb2c30 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantBindElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/RedundantCallElimination.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,11 @@ import org.jetbrains.kotlin.js.backend.ast.JsBlock import org.jetbrains.kotlin.js.backend.ast.JsInvocation import org.jetbrains.kotlin.js.backend.ast.JsNameRef import org.jetbrains.kotlin.js.backend.ast.RecursiveJsVisitor +import org.jetbrains.kotlin.js.inline.util.getCallerQualifier +import org.jetbrains.kotlin.js.inline.util.isCallInvocation -// TODO: this optimization is a little unfair. It tries to recognize pattern like this a.bind(b)(args) and -// replace it with b.a(args). However, we can't be completely sure that `a` is a Function. -// Using JS-independent AST should solve the issue (as well as many other issues). -class RedundantBindElimination(private val root: JsBlock) { +// Replaces a.foo.call(a, b) with a.foo(b) +class RedundantCallElimination(private val root: JsBlock) { private var changed = false fun apply(): Boolean { @@ -35,15 +35,18 @@ class RedundantBindElimination(private val root: JsBlock) { } private fun tryEliminate(invocation: JsInvocation) { - val qualifier = invocation.qualifier as? JsInvocation ?: return + if (!isCallInvocation(invocation)) return - val outerQualifier = qualifier.qualifier as? JsNameRef ?: return - val name = outerQualifier.ident - if (name != "bind") return + val qualifier = getCallerQualifier(invocation) as? JsNameRef ?: return - val qualifierReplacement = outerQualifier.qualifier ?: return - invocation.qualifier = qualifierReplacement - changed = true + val receiver = qualifier.qualifier as? JsNameRef ?: return + val firstArg = invocation.arguments.firstOrNull() as? JsNameRef ?: return + + if (receiver.qualifier == null && receiver.name != null && firstArg.qualifier == null && receiver.name == firstArg.name) { + invocation.arguments.removeAt(0) + invocation.qualifier = qualifier + changed = true + } } }) diff --git a/js/js.libraries/src/core/coroutines.kt b/js/js.libraries/src/core/coroutines.kt index 4ec04fe2d76..5152ee82ff0 100644 --- a/js/js.libraries/src/core/coroutines.kt +++ b/js/js.libraries/src/core/coroutines.kt @@ -28,7 +28,7 @@ import kotlin.coroutines.intrinsics.* public fun (suspend R.() -> T).createCoroutine( receiver: R, completion: Continuation -): Continuation = this.asDynamic().call(receiver, completion, true).facade +): Continuation = this.asDynamic()(receiver, completion, true).facade /** * Starts coroutine with receiver type [R] and result type [T]. @@ -40,7 +40,7 @@ public fun (suspend R.() -> T).startCoroutine( receiver: R, completion: Continuation ) { - this.asDynamic().call(receiver, completion) + this.asDynamic()(receiver, completion) } /** diff --git a/js/js.libraries/src/js/callableReferenceUtils.js b/js/js.libraries/src/js/callableReferenceUtils.js index c7096a7179f..3e7fa007089 100644 --- a/js/js.libraries/src/js/callableReferenceUtils.js +++ b/js/js.libraries/src/js/callableReferenceUtils.js @@ -45,20 +45,6 @@ Kotlin.getBoundCallableRefForExtensionFunction = function (receiver, extFun) { }; }; -Kotlin.getCallableRefForLocalExtensionFunction = function (extFun) { - return function () { - var args = [].slice.call(arguments); - var instance = args.shift(); - return extFun.apply(instance, args); - }; -}; - -Kotlin.getBoundCallableRefForLocalExtensionFunction = function (receiver, extFun) { - return function () { - return extFun.apply(receiver, arguments); - }; -}; - Kotlin.getCallableRefForConstructor = function (klass) { return function () { var obj = Object.create(klass.prototype); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CallableReferenceInlineTestsGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CallableReferenceInlineTestsGenerated.java index c4d901d4f09..78960a873e0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CallableReferenceInlineTestsGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/CallableReferenceInlineTestsGenerated.java @@ -39,25 +39,13 @@ public class CallableReferenceInlineTestsGenerated extends AbstractCallableRefer @TestMetadata("classLevel.kt") public void testClassLevel() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/classLevel.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("classLevel2.kt") public void testClassLevel2() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/classLevel2.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("constructor.kt") @@ -111,13 +99,7 @@ public class CallableReferenceInlineTestsGenerated extends AbstractCallableRefer @TestMetadata("topLevelExtension.kt") public void testTopLevelExtension() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelExtension.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("topLevelProperty.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 ac00612e93c..e2e2143c22c 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 @@ -8127,6 +8127,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("kt13312.kt") + public void testKt13312() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt13312.kt"); + doTest(fileName); + } + @TestMetadata("kt1776.kt") public void testKt1776() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt1776.kt"); @@ -8160,13 +8166,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("kt3646.kt") public void testKt3646() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/extensionFunctions/kt3646.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("kt3969.kt") @@ -8966,13 +8966,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("castFunctionToExtension.kt") public void testCastFunctionToExtension() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/invoke/castFunctionToExtension.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("extensionInvokeOnExpr.kt") @@ -9173,13 +9167,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("kt4989.kt") public void testKt4989() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/kt4989.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("localExtensionOnNullableParameter.kt") @@ -12657,13 +12645,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("kt4987.kt") public void testKt4987() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/operatorConventions/kt4987.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("nestedMaps.kt") @@ -16607,13 +16589,7 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { @TestMetadata("functionFromStdlib.kt") public void testFunctionFromStdlib() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt"); - try { - doTest(fileName); - } - catch (Throwable ignore) { - return; - } - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that."); + doTest(fileName); } @TestMetadata("functionReferenceErasedToKFunction.kt") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt index 868aaa1b4f4..d1818c57169 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.js.translate.callTranslator import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor -import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.js.PredefinedAnnotation import org.jetbrains.kotlin.js.backend.ast.* @@ -101,20 +100,12 @@ object DefaultFunctionCallCase : FunctionCallCase() { val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context) - val referenceToCall = - if (callableDescriptor.visibility == Visibilities.LOCAL) { - Namer.getFunctionCallRef(functionRef) - } - else { - functionRef - } - - return JsInvocation(referenceToCall, argumentsInfo.argsWithReceiver(extensionReceiver!!)) + return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(extensionReceiver!!)) } override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native - val functionRef = JsNameRef(functionName, dispatchReceiver!!) + val functionRef = JsAstUtils.pureFqn(functionName, dispatchReceiver!!) return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(extensionReceiver!!)) } } @@ -170,14 +161,7 @@ object InvokeIntrinsic : FunctionCallCase() { } override fun FunctionCallInfo.dispatchReceiver(): JsExpression { - val receiver = resolvedCall.dispatchReceiver!! - val jsReceiver = if (receiver.type.isExtensionFunctionType) { - pureFqn(Namer.CALL_FUNCTION, dispatchReceiver) - } - else { - dispatchReceiver!! - } - return JsInvocation(jsReceiver, argumentsInfo.translateArguments) + return JsInvocation(dispatchReceiver!!, argumentsInfo.translateArguments) } /** @@ -194,7 +178,7 @@ object InvokeIntrinsic : FunctionCallCase() { * extLambda.call(obj, some, args) */ override fun FunctionCallInfo.bothReceivers(): JsExpression { - return JsInvocation(Namer.getFunctionCallRef(dispatchReceiver!!), argumentsInfo.argsWithReceiver(extensionReceiver!!)) + return JsInvocation(dispatchReceiver!!, argumentsInfo.argsWithReceiver(extensionReceiver!!)) } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt index cfa5a188b9a..f66617fe74a 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/VariableCallCases.kt @@ -130,7 +130,7 @@ object DefaultVariableAccessCase : VariableAccessCase() { } override fun VariableAccessInfo.bothReceivers(): JsExpression { - val funRef = JsNameRef(context.getNameForDescriptor(getAccessDescriptorIfNeeded()), dispatchReceiver!!) + val funRef = JsAstUtils.pureFqn(context.getNameForDescriptor(getAccessDescriptorIfNeeded()), dispatchReceiver!!) return JsInvocation(funRef, extensionReceiver!!, *additionalArguments.toTypedArray()) } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index dcb57144a69..11a5195e90c 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -211,10 +211,6 @@ public final class Namer { @NotNull private final JsName boundCallableRefForExtensionFunctionName; @NotNull - private final JsName callableRefForLocalExtensionFunctionName; - @NotNull - private final JsName boundCallableRefForLocalExtensionFunctionName; - @NotNull private final JsName callableRefForConstructorName; @NotNull private final JsName callableRefForTopLevelProperty; @@ -244,8 +240,6 @@ public final class Namer { boundCallableRefForMemberFunctionName = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME); callableRefForExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME); boundCallableRefForExtensionFunctionName = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME); - callableRefForLocalExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME); - boundCallableRefForLocalExtensionFunctionName = kotlinScope.declareName(BOUND_CALLABLE_REF_FOR_LOCAL_EXTENSION_FUNCTION_NAME); callableRefForConstructorName = kotlinScope.declareName(CALLABLE_REF_FOR_CONSTRUCTOR_NAME); callableRefForTopLevelProperty = kotlinScope.declareName(CALLABLE_REF_FOR_TOP_LEVEL_PROPERTY); callableRefForMemberProperty = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_PROPERTY); @@ -287,16 +281,6 @@ public final class Namer { return kotlin(boundCallableRefForExtensionFunctionName); } - @NotNull - public JsExpression callableRefForLocalExtensionFunctionReference() { - return kotlin(callableRefForLocalExtensionFunctionName); - } - - @NotNull - public JsExpression boundCallableRefForLocalExtensionFunctionReference() { - return kotlin(boundCallableRefForLocalExtensionFunctionName); - } - @NotNull public JsExpression callableRefForConstructorReference() { return kotlin(callableRefForConstructorName); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt index 507bcfc6dc0..a56f1cc8287 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/FunctionTranslator.kt @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.expression import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor -import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.js.backend.ast.JsExpression import org.jetbrains.kotlin.js.backend.ast.JsFunction import org.jetbrains.kotlin.js.backend.ast.JsParameter @@ -77,7 +76,7 @@ private fun FunctionDescriptor.getCorrectTypeParameters() = private val FunctionDescriptor.requiresExtensionReceiverParameter - get() = DescriptorUtils.isExtension(this) && visibility != Visibilities.LOCAL + get() = DescriptorUtils.isExtension(this) fun TranslationContext.translateFunction(declaration: KtDeclarationWithBody, function: JsFunction) { val descriptor = BindingUtils.getFunctionDescriptor(bindingContext(), declaration) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt index 4782a398481..35ece57cddb 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/CallableReferenceTranslator.kt @@ -223,15 +223,7 @@ object CallableReferenceTranslator { receiver: JsExpression? ): JsExpression { val jsFunctionRef = ReferenceTranslator.translateAsValueReference(descriptor, context) - if (descriptor.visibility == Visibilities.LOCAL) { - if (receiver == null) { - return JsInvocation(context.namer().callableRefForLocalExtensionFunctionReference(), jsFunctionRef) - } - else { - return JsInvocation(context.namer().boundCallableRefForLocalExtensionFunctionReference(), receiver, jsFunctionRef) - } - } - else if (AnnotationsUtils.isNativeObject(descriptor)) { + if (AnnotationsUtils.isNativeObject(descriptor)) { return translateForMemberFunction(descriptor, context, receiver) } else { diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/VariableAccessTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/VariableAccessTranslator.java index 3eaac3aec6b..d5193ac3686 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/VariableAccessTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/reference/VariableAccessTranslator.java @@ -16,12 +16,12 @@ package org.jetbrains.kotlin.js.translate.reference; -import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation; -import org.jetbrains.kotlin.js.backend.ast.JsExpression; -import org.jetbrains.kotlin.js.backend.ast.JsNameRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation; +import org.jetbrains.kotlin.js.backend.ast.JsExpression; +import org.jetbrains.kotlin.js.backend.ast.JsNameRef; import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.general.AbstractTranslator; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/inlineUtils.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/inlineUtils.kt index 192eeff1d56..65135d545c7 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/inlineUtils.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/inlineUtils.kt @@ -18,11 +18,9 @@ package org.jetbrains.kotlin.js.translate.utils -import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor -import org.jetbrains.kotlin.js.backend.ast.metadata.inlineStrategy -import org.jetbrains.kotlin.js.backend.ast.metadata.psiElement import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.metadata.* import org.jetbrains.kotlin.js.inline.util.isCallInvocation import org.jetbrains.kotlin.js.translate.context.TranslationContext import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator diff --git a/js/js.translator/testData/box/native/passExtLambdaFromNative.js b/js/js.translator/testData/box/native/passExtLambdaFromNative.js index e185f90ebc4..b9fe2971bab 100644 --- a/js/js.translator/testData/box/native/passExtLambdaFromNative.js +++ b/js/js.translator/testData/box/native/passExtLambdaFromNative.js @@ -3,5 +3,5 @@ function A(v) { } function nativeBox(b) { - return b.bar_asnz92$(new A("foo"), function(i, s) { return "" + this.v + s + i }) + return b.bar_asnz92$(new A("foo"), function($reciever, i, s) { return "" + $reciever.v + s + i }) } diff --git a/js/js.translator/testData/box/native/passExtLambdaToNative.js b/js/js.translator/testData/box/native/passExtLambdaToNative.js index 23727858fec..16ba8964fa7 100644 --- a/js/js.translator/testData/box/native/passExtLambdaToNative.js +++ b/js/js.translator/testData/box/native/passExtLambdaToNative.js @@ -3,5 +3,5 @@ function A(v) { } function bar(a, extLambda) { - return extLambda.call(a, 4, "boo") + return extLambda(a, 4, "boo") } diff --git a/js/js.translator/testData/box/native/passMemberOrExtToNative.js b/js/js.translator/testData/box/native/passMemberOrExtToNative.js index 39df1fd518a..49d87c5f457 100644 --- a/js/js.translator/testData/box/native/passMemberOrExtToNative.js +++ b/js/js.translator/testData/box/native/passMemberOrExtToNative.js @@ -1,3 +1,3 @@ function bar(a, extLambda) { - return extLambda.call(a, 4, "boo") + return extLambda(a, 4, "boo") }