Obtain correct captured suspend local function
if we call the function inside, for example, lambda. #KT-28844 Fixed
This commit is contained in:
@@ -885,6 +885,7 @@ public abstract class StackValue {
|
|||||||
// 2) call using callable reference: in this case it is not local, but rather captured value
|
// 2) call using callable reference: in this case it is not local, but rather captured value
|
||||||
// 3) recursive call: we are in the middle of defining it, but, thankfully, we can simply call `this.invoke` to
|
// 3) recursive call: we are in the middle of defining it, but, thankfully, we can simply call `this.invoke` to
|
||||||
// create new coroutine
|
// create new coroutine
|
||||||
|
// 4) Normal call, but the value is captured
|
||||||
|
|
||||||
// First, check whether this is a normal call
|
// First, check whether this is a normal call
|
||||||
int index = codegen.lookupLocalIndex(callee);
|
int index = codegen.lookupLocalIndex(callee);
|
||||||
@@ -898,24 +899,27 @@ public abstract class StackValue {
|
|||||||
Type calleeType = CodegenBinding.asmTypeForAnonymousClass(bindingContext, callee);
|
Type calleeType = CodegenBinding.asmTypeForAnonymousClass(bindingContext, callee);
|
||||||
if (codegen.context.hasThisDescriptor()) {
|
if (codegen.context.hasThisDescriptor()) {
|
||||||
ClassDescriptor thisDescriptor = codegen.context.getThisDescriptor();
|
ClassDescriptor thisDescriptor = codegen.context.getThisDescriptor();
|
||||||
|
ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_CALLABLE, callee);
|
||||||
if (thisDescriptor instanceof SyntheticClassDescriptorForLambda &&
|
if (thisDescriptor instanceof SyntheticClassDescriptorForLambda &&
|
||||||
((SyntheticClassDescriptorForLambda) thisDescriptor).isCallableReference()) {
|
((SyntheticClassDescriptorForLambda) thisDescriptor).isCallableReference()) {
|
||||||
// Call is inside a callable reference
|
// Call is inside a callable reference
|
||||||
// if it is call to recursive local, just return this$0
|
// if it is call to recursive local, just return this$0
|
||||||
Boolean isRecursive = bindingContext.get(RECURSIVE_SUSPEND_CALLABLE_REFERENCE, thisDescriptor);
|
Boolean isRecursive = bindingContext.get(RECURSIVE_SUSPEND_CALLABLE_REFERENCE, thisDescriptor);
|
||||||
if (isRecursive != null && isRecursive) {
|
if (isRecursive != null && isRecursive) {
|
||||||
ClassDescriptor classDescriptor =
|
|
||||||
bindingContext.get(CLASS_FOR_CALLABLE, callee);
|
|
||||||
assert classDescriptor != null : "No CLASS_FOR_CALLABLE" + callee;
|
assert classDescriptor != null : "No CLASS_FOR_CALLABLE" + callee;
|
||||||
return thisOrOuter(codegen, classDescriptor, false, false);
|
return thisOrOuter(codegen, classDescriptor, false, false);
|
||||||
}
|
}
|
||||||
// Otherwise, just call constructor of the closure
|
// Otherwise, just call constructor of the closure
|
||||||
return codegen.findCapturedValue(callee);
|
return codegen.findCapturedValue(callee);
|
||||||
}
|
}
|
||||||
|
if (classDescriptor == thisDescriptor) {
|
||||||
|
// Recursive suspend local function, just call invoke on this, it will create new coroutine automatically
|
||||||
|
codegen.v.visitVarInsn(ALOAD, 0);
|
||||||
|
return onStack(calleeType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Recursive suspend local function, just call invoke on this, it will create new coroutine automatically
|
// Otherwise, this is captured value
|
||||||
codegen.v.visitVarInsn(ALOAD, 0);
|
return codegen.findCapturedValue(callee);
|
||||||
return onStack(calleeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
|
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
// COMMON_COROUTINES_TEST
|
||||||
|
// IGNORE_BACKEND: JVM_IR, NATIVE
|
||||||
|
|
||||||
|
import helpers.*
|
||||||
|
import COROUTINES_PACKAGE.*
|
||||||
|
|
||||||
|
fun builder(block: suspend Unit.() -> Unit) {
|
||||||
|
block.startCoroutine(Unit, EmptyContinuation)
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = "FAIL 1"
|
||||||
|
|
||||||
|
fun testOuterJobIsCancelled() = builder {
|
||||||
|
suspend fun callJobScoped() = "OK"
|
||||||
|
|
||||||
|
val outerJob = suspend {
|
||||||
|
res = callJobScoped()
|
||||||
|
}
|
||||||
|
outerJob()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testOuterJobIsCancelled2() = builder {
|
||||||
|
suspend fun callJobScoped() = "OK"
|
||||||
|
|
||||||
|
suspend fun outerJob() {
|
||||||
|
res = callJobScoped()
|
||||||
|
}
|
||||||
|
outerJob()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
testOuterJobIsCancelled()
|
||||||
|
if (res != "OK") return res
|
||||||
|
res = "FAIL 2"
|
||||||
|
testOuterJobIsCancelled2()
|
||||||
|
return res
|
||||||
|
}
|
||||||
+10
@@ -5906,6 +5906,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lastExpressionIsLoop.kt")
|
@TestMetadata("lastExpressionIsLoop.kt")
|
||||||
public void testLastExpressionIsLoop_1_2() throws Exception {
|
public void testLastExpressionIsLoop_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+10
@@ -5906,6 +5906,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lastExpressionIsLoop.kt")
|
@TestMetadata("lastExpressionIsLoop.kt")
|
||||||
public void testLastExpressionIsLoop_1_2() throws Exception {
|
public void testLastExpressionIsLoop_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+10
@@ -5906,6 +5906,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lastExpressionIsLoop.kt")
|
@TestMetadata("lastExpressionIsLoop.kt")
|
||||||
public void testLastExpressionIsLoop_1_2() throws Exception {
|
public void testLastExpressionIsLoop_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
+5
@@ -4851,6 +4851,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lastExpressionIsLoop.kt")
|
@TestMetadata("lastExpressionIsLoop.kt")
|
||||||
public void testLastExpressionIsLoop_1_3() throws Exception {
|
public void testLastExpressionIsLoop_1_3() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines");
|
||||||
|
|||||||
+10
@@ -5046,6 +5046,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt25912.kt", "kotlin.coroutines");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_2() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines.experimental");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt28844.kt")
|
||||||
|
public void testKt28844_1_3() throws Exception {
|
||||||
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/kt28844.kt", "kotlin.coroutines");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lastExpressionIsLoop.kt")
|
@TestMetadata("lastExpressionIsLoop.kt")
|
||||||
public void testLastExpressionIsLoop_1_2() throws Exception {
|
public void testLastExpressionIsLoop_1_2() throws Exception {
|
||||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt", "kotlin.coroutines.experimental");
|
||||||
|
|||||||
Reference in New Issue
Block a user