JS: support callable references on suspend functions (KT-30987 fixed)
This commit is contained in:
Vendored
-1
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// IGNORE_BACKEND: JVM_IR
|
// IGNORE_BACKEND: JVM_IR
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// IGNORE_BACKEND: JVM_IR
|
// IGNORE_BACKEND: JVM_IR
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// !LANGUAGE: +ReleaseCoroutines
|
||||||
|
// IGNORE_BACKEND: JVM_IR
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
import helpers.*
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.coroutines.intrinsics.*
|
||||||
|
|
||||||
|
fun builder(c: suspend () -> Unit) {
|
||||||
|
c.startCoroutine(EmptyContinuation)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun id(s: String) = s
|
||||||
|
|
||||||
|
suspend fun String.idExt() = this
|
||||||
|
|
||||||
|
class A {
|
||||||
|
suspend fun id(s: String) = s
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun run(block: suspend () -> String) = block()
|
||||||
|
|
||||||
|
inline suspend fun runInline(block: suspend () -> String) = block()
|
||||||
|
|
||||||
|
suspend fun O(block: suspend (String) -> String) = block("O")
|
||||||
|
|
||||||
|
inline suspend fun K(block: suspend (String) -> String) = block("K")
|
||||||
|
|
||||||
|
suspend fun ok(o: String): String {
|
||||||
|
return o + run {
|
||||||
|
if (o != "K") {
|
||||||
|
(::ok)("K")
|
||||||
|
} else ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
builder {
|
||||||
|
result = O(::id) + K(::id)
|
||||||
|
result += run("O"::idExt) + runInline("K"::idExt)
|
||||||
|
|
||||||
|
val a = A()
|
||||||
|
result += O(a::id) + K(a::id)
|
||||||
|
|
||||||
|
result += ok("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != "OKOKOKOK") return "fail: $result"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +ReleaseCoroutines
|
// !LANGUAGE: +ReleaseCoroutines
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// IGNORE_BACKEND: JVM_IR
|
// IGNORE_BACKEND: JVM_IR
|
||||||
// NO_CHECK_LAMBDA_INLINING
|
// NO_CHECK_LAMBDA_INLINING
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
|
|||||||
+5
@@ -6267,6 +6267,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleSuspendCallableReference.kt")
|
||||||
|
public void testSimpleSuspendCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simpleWithHandleResult.kt")
|
@TestMetadata("simpleWithHandleResult.kt")
|
||||||
public void testSimpleWithHandleResult_1_2() throws Exception {
|
public void testSimpleWithHandleResult_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+5
@@ -6267,6 +6267,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleSuspendCallableReference.kt")
|
||||||
|
public void testSimpleSuspendCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simpleWithHandleResult.kt")
|
@TestMetadata("simpleWithHandleResult.kt")
|
||||||
public void testSimpleWithHandleResult_1_2() throws Exception {
|
public void testSimpleWithHandleResult_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+5
@@ -6267,6 +6267,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleSuspendCallableReference.kt")
|
||||||
|
public void testSimpleSuspendCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simpleWithHandleResult.kt")
|
@TestMetadata("simpleWithHandleResult.kt")
|
||||||
public void testSimpleWithHandleResult_1_2() throws Exception {
|
public void testSimpleWithHandleResult_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
@@ -44,17 +44,14 @@ class CoroutineTransformer : JsVisitorWithContextImpl() {
|
|||||||
return super.visit(x, ctx)
|
return super.visit(x, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(x: JsFunction, ctx: JsContext<*>): Boolean {
|
override fun endVisit(x: JsFunction, ctx: JsContext<*>) {
|
||||||
if (x.isInlineableCoroutineBody) {
|
if (x.isInlineableCoroutineBody) {
|
||||||
x.body = transformCoroutineMetadataToSpecialFunctions(x.body)
|
x.body = transformCoroutineMetadataToSpecialFunctions(x.body)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if (x.coroutineMetadata != null) {
|
if (x.coroutineMetadata != null) {
|
||||||
lastStatementLevelContext.addPrevious(CoroutineFunctionTransformer(x, functionName[x]).transform())
|
lastStatementLevelContext.addPrevious(CoroutineFunctionTransformer(x, functionName[x]).transform())
|
||||||
x.coroutineMetadata = null
|
x.coroutineMetadata = null
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
return super.visit(x, ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(x: JsVars.JsVar, ctx: JsContext<*>): Boolean {
|
override fun visit(x: JsVars.JsVar, ctx: JsContext<*>): Boolean {
|
||||||
|
|||||||
Generated
+5
@@ -5072,6 +5072,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleSuspendCallableReference.kt")
|
||||||
|
public void testSimpleSuspendCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simpleWithHandleResult.kt")
|
@TestMetadata("simpleWithHandleResult.kt")
|
||||||
public void testSimpleWithHandleResult_1_3() throws Exception {
|
public void testSimpleWithHandleResult_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines");
|
||||||
|
|||||||
+5
@@ -5397,6 +5397,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleException.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleSuspendCallableReference.kt")
|
||||||
|
public void testSimpleSuspendCallableReference() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/coroutines/simpleSuspendCallableReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simpleWithHandleResult.kt")
|
@TestMetadata("simpleWithHandleResult.kt")
|
||||||
public void testSimpleWithHandleResult_1_2() throws Exception {
|
public void testSimpleWithHandleResult_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+5
-3
@@ -540,9 +540,11 @@ public class TranslationContext {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||||
JsExpression nameRef = captureIfNeedAndGetCapturedName(descriptor);
|
if (continuationParameterDescriptor != descriptor) {
|
||||||
if (nameRef != null) {
|
JsExpression nameRef = captureIfNeedAndGetCapturedName(descriptor);
|
||||||
return nameRef;
|
if (nameRef != null) {
|
||||||
|
return nameRef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsExpression alias = aliasingContext.getAliasForDescriptor(descriptor);
|
JsExpression alias = aliasingContext.getAliasForDescriptor(descriptor);
|
||||||
|
|||||||
+13
-4
@@ -24,9 +24,7 @@ import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
|
|||||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
import org.jetbrains.kotlin.js.translate.utils.*
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
|
||||||
import org.jetbrains.kotlin.js.translate.utils.finalElement
|
|
||||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getFunctionResolvedCallWithAssert
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getFunctionResolvedCallWithAssert
|
||||||
@@ -127,7 +125,18 @@ object CallableReferenceTranslator {
|
|||||||
val type = functionDescriptor.valueParameters[index].type
|
val type = functionDescriptor.valueParameters[index].type
|
||||||
aliases[valueArg.getArgumentExpression()!!] = TranslationUtils.coerce(context, paramRef, type)
|
aliases[valueArg.getArgumentExpression()!!] = TranslationUtils.coerce(context, paramRef, type)
|
||||||
}
|
}
|
||||||
val functionContext = context.innerBlock(function.body).innerContextWithAliasesForExpressions(aliases)
|
|
||||||
|
var functionContext = context.innerBlock(function.body).innerContextWithAliasesForExpressions(aliases).inner(functionDescriptor)
|
||||||
|
|
||||||
|
functionContext.continuationParameterDescriptor?.let { continuationDescriptor ->
|
||||||
|
function.parameters += JsParameter(context.getNameForDescriptor(continuationDescriptor))
|
||||||
|
functionContext = functionContext.innerContextWithDescriptorsAliased(mapOf(continuationDescriptor to JsAstUtils.stateMachineReceiver()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionDescriptor.isSuspend) {
|
||||||
|
function.fillCoroutineMetadata(functionContext, descriptor, hasController = false)
|
||||||
|
}
|
||||||
|
|
||||||
val invocation = CallTranslator.translate(functionContext, fakeResolvedCall, receiverParam)
|
val invocation = CallTranslator.translate(functionContext, fakeResolvedCall, receiverParam)
|
||||||
function.body.statements += JsReturn(TranslationUtils.coerce(context, invocation, context.currentModule.builtIns.anyType))
|
function.body.statements += JsReturn(TranslationUtils.coerce(context, invocation, context.currentModule.builtIns.anyType))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user