From 81798282b9e29f5b9ad3f518aac2b2ad6c39d75b Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Thu, 9 Apr 2020 15:34:11 +0300 Subject: [PATCH] JS: support explicit SAM constructor invocation --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../box/funInterface/primitiveConversions.kt | 30 +++++++++++++++-- .../samConstructorExplicitInvocation.kt | 33 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ .../callTranslator/FunctionCallCases.kt | 8 ++++- .../translate/declaration/ClassTranslator.kt | 2 +- 10 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.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 90539e5874ce7..3a1e1f060c9e3 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 @@ -11029,6 +11029,11 @@ public void testReceiverEvaluatedOnce() throws Exception { runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt"); } + @TestMetadata("samConstructorExplicitInvocation.kt") + public void testSamConstructorExplicitInvocation() throws Exception { + runTest("compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt"); + } + @TestMetadata("suspendFunInterfaceConversionCodegen.kt") public void testSuspendFunInterfaceConversionCodegen() throws Exception { runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt"); diff --git a/compiler/testData/codegen/box/funInterface/primitiveConversions.kt b/compiler/testData/codegen/box/funInterface/primitiveConversions.kt index 5386659a71618..1650ebf0387f5 100644 --- a/compiler/testData/codegen/box/funInterface/primitiveConversions.kt +++ b/compiler/testData/codegen/box/funInterface/primitiveConversions.kt @@ -10,11 +10,37 @@ fun interface CharToAny { fun invoke(c: Char): Any } -fun foo(c: CharToAny): Any = c.invoke('O') +fun interface GenericToAny { + fun invoke(t: T): Any +} + +fun interface GenericCharToAny: GenericToAny + +fun foo1(c: CharToAny): Any = c.invoke('1') + +fun foo2(t: T, g: GenericToAny): Any = g.invoke(t) + +fun foo3(c: GenericCharToAny) = c.invoke('3') fun box(): String { - if (foo { it } !is Char) return "fail" + val c1 = foo1 { it } + if (c1 !is Char || c1 != '1') return "fail1" + + val c2 = foo2('2') { it } + if (c2 !is Char || c2 != '2') return "fail2" + + val c3 = foo3 { it } + if (c3 !is Char || c3 != '3') return "fail3" + + val c4 = CharToAny { it }.invoke('4') + if (c4 !is Char || c4 != '4') return "fail4" + + val c5 = GenericToAny { it }.invoke('5') + if (c5 !is Char || c5 != '5') return "fail5" + + val c6 = GenericCharToAny { it }.invoke('6') + if (c6 !is Char || c6 != '6') return "fail6" return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt b/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt new file mode 100644 index 0000000000000..2c37c3adbb213 --- /dev/null +++ b/compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +FunctionalInterfaceConversion +// IGNORE_BACKEND_FIR: JVM_IR +// SKIP_DCE_DRIVEN + +fun interface S { + fun invoke(): String +} + +fun interface G { + fun foo(t: T): T +} + +fun interface C: G + +fun interface C2 { + fun bar(c: Char): Char +} + +fun box(): String { + val g = G { it * 10 } + if (g.foo(2) != 20) return "fail1" + + val g2 = G { a: Char -> a + 1 } + if (g2.foo('a') != 'b') return "fail2" + + val c = C { it + 2 } + if (c.foo('A') != 'C') return "fail3" + + val c2 = C2 { it + 3 } + if (c2.bar('0') != '3') return "fail4" + + return S { "OK" }.invoke() +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 6ce6c3ec43a89..7da7444916bcb 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -12244,6 +12244,11 @@ public void testReceiverEvaluatedOnce() throws Exception { runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt"); } + @TestMetadata("samConstructorExplicitInvocation.kt") + public void testSamConstructorExplicitInvocation() throws Exception { + runTest("compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt"); + } + @TestMetadata("suspendFunInterfaceConversionCodegen.kt") public void testSuspendFunInterfaceConversionCodegen() throws Exception { runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index b262b6308762d..26b63cfeee3b5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -12244,6 +12244,11 @@ public void testReceiverEvaluatedOnce() throws Exception { runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt"); } + @TestMetadata("samConstructorExplicitInvocation.kt") + public void testSamConstructorExplicitInvocation() throws Exception { + runTest("compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt"); + } + @TestMetadata("suspendFunInterfaceConversionCodegen.kt") public void testSuspendFunInterfaceConversionCodegen() throws Exception { runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index d9778600e2b5a..1040b15813dea 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11029,6 +11029,11 @@ public void testReceiverEvaluatedOnce() throws Exception { runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt"); } + @TestMetadata("samConstructorExplicitInvocation.kt") + public void testSamConstructorExplicitInvocation() throws Exception { + runTest("compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt"); + } + @TestMetadata("suspendFunInterfaceConversionCodegen.kt") public void testSuspendFunInterfaceConversionCodegen() throws Exception { runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.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 57a92b684a823..8780dedebd58e 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 @@ -9444,6 +9444,11 @@ public void testReceiverEvaluatedOnce() throws Exception { runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt"); } + @TestMetadata("samConstructorExplicitInvocation.kt") + public void testSamConstructorExplicitInvocation() throws Exception { + runTest("compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt"); + } + @TestMetadata("suspendFunInterfaceConversionCodegen.kt") public void testSuspendFunInterfaceConversionCodegen() throws Exception { runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.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 657d6a58d76a8..e5847b9229abf 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 @@ -9444,6 +9444,11 @@ public void testReceiverEvaluatedOnce() throws Exception { runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt"); } + @TestMetadata("samConstructorExplicitInvocation.kt") + public void testSamConstructorExplicitInvocation() throws Exception { + runTest("compiler/testData/codegen/box/funInterface/samConstructorExplicitInvocation.kt"); + } + @TestMetadata("suspendFunInterfaceConversionCodegen.kt") public void testSuspendFunInterfaceConversionCodegen() throws Exception { runTest("compiler/testData/codegen/box/funInterface/suspendFunInterfaceConversionCodegen.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 50eafe54d5f15..bbe5b2b5d8d69 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 @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor import org.jetbrains.kotlin.util.OperatorNameConventions import java.util.* @@ -184,7 +185,7 @@ object InvokeIntrinsic : FunctionCallCase() { object ConstructorCallCase : FunctionCallCase() { fun canApply(callInfo: FunctionCallInfo): Boolean { - return callInfo.callableDescriptor is ConstructorDescriptor + return callInfo.callableDescriptor is ConstructorDescriptor || callInfo.callableDescriptor is SamConstructorDescriptor } override fun FunctionCallInfo.noReceivers() = doTranslate { translateArguments } @@ -197,6 +198,11 @@ object ConstructorCallCase : FunctionCallCase() { getArguments: CallArgumentTranslator.ArgumentsInfo.() -> List ): JsExpression { val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context) + + if (callableDescriptor is SamConstructorDescriptor) { + return JsNew(functionRef, argumentsInfo.getArguments()) + } + val invocationArguments = mutableListOf() val constructorDescriptor = callableDescriptor as ClassConstructorDescriptor diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt index 579d32e3f1529..de0c9a7484b13 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt @@ -592,7 +592,7 @@ class ClassTranslator private constructor( listOfNotNull(innerContext.continuationParameterDescriptor) val arguments = parameters.map { - TranslationUtils.coerce(innerContext, innerContext.getAliasForDescriptor(it)!!, context.currentModule.builtIns.anyType) + TranslationUtils.coerce(innerContext, ReferenceTranslator.translateAsValueReference(it, innerContext), context.currentModule.builtIns.anyType) } function.body = JsBlock(JsReturn(JsInvocation(pureFqn(Namer.SAM_FIELD_NAME, JsThisRef()), arguments)))