Fix super calls to suspend functions in abstract classes
This commit is contained in:
@@ -81,6 +81,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isAnnotationOrJvmInter
|
|||||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
|
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
|
||||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
||||||
|
import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable;
|
||||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
||||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
|
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
||||||
@@ -203,7 +204,8 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isOpenSuspendInClass =
|
boolean isOpenSuspendInClass =
|
||||||
functionDescriptor.isSuspend() && DescriptorUtilKt.isEffectivelyOpen(functionDescriptor) &&
|
functionDescriptor.isSuspend() &&
|
||||||
|
functionDescriptor.getModality() != Modality.ABSTRACT && isOverridable(functionDescriptor) &&
|
||||||
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
!isInterface(functionDescriptor.getContainingDeclaration()) &&
|
||||||
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
origin.getOriginKind() != JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL;
|
||||||
|
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ class CoroutineCodegenForNamedFunction private constructor(
|
|||||||
|
|
||||||
codegen.v.load(0, AsmTypes.OBJECT_TYPE)
|
codegen.v.load(0, AsmTypes.OBJECT_TYPE)
|
||||||
|
|
||||||
if (suspendFunctionJvmView.isEffectivelyOpen() && !isInterfaceMethod && captureThisType != null) {
|
if (suspendFunctionJvmView.isOverridable && !isInterfaceMethod && captureThisType != null) {
|
||||||
val owner = captureThisType.internalName
|
val owner = captureThisType.internalName
|
||||||
val impl = callableMethod.getAsmMethod().getImplForOpenMethod(owner)
|
val impl = callableMethod.getAsmMethod().getImplForOpenMethod(owner)
|
||||||
codegen.v.invokestatic(owner, impl.name, impl.descriptor, false)
|
codegen.v.invokestatic(owner, impl.name, impl.descriptor, false)
|
||||||
|
|||||||
Vendored
+41
@@ -0,0 +1,41 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_COROUTINES
|
||||||
|
import helpers.*
|
||||||
|
import kotlin.coroutines.experimental.*
|
||||||
|
import kotlin.coroutines.experimental.intrinsics.*
|
||||||
|
|
||||||
|
abstract class A(val v: String) {
|
||||||
|
suspend abstract fun foo(v: String): String
|
||||||
|
|
||||||
|
suspend fun suspendThere(v: String): String = suspendCoroutineOrReturn { x ->
|
||||||
|
x.resume(v)
|
||||||
|
COROUTINE_SUSPENDED
|
||||||
|
}
|
||||||
|
|
||||||
|
open suspend fun suspendHere(): String = foo("O") + suspendThere(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
class B(v: String) : A(v) {
|
||||||
|
override suspend fun foo(v: String): String = suspendCoroutineOrReturn { x ->
|
||||||
|
x.resume(v)
|
||||||
|
COROUTINE_SUSPENDED
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun suspendHere(): String = super.suspendHere() + suspendThere("56")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(c: suspend A.() -> Unit) {
|
||||||
|
c.startCoroutine(B("K"), EmptyContinuation)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
builder {
|
||||||
|
result = suspendHere()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != "OK56") return "fail 1: $result"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+6
@@ -5734,6 +5734,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("superCallAbstractClass.kt")
|
||||||
|
public void testSuperCallAbstractClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallAbstractClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("superCallInterface.kt")
|
@TestMetadata("superCallInterface.kt")
|
||||||
public void testSuperCallInterface() throws Exception {
|
public void testSuperCallInterface() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
||||||
|
|||||||
@@ -5734,6 +5734,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("superCallAbstractClass.kt")
|
||||||
|
public void testSuperCallAbstractClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallAbstractClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("superCallInterface.kt")
|
@TestMetadata("superCallInterface.kt")
|
||||||
public void testSuperCallInterface() throws Exception {
|
public void testSuperCallInterface() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
||||||
|
|||||||
@@ -5734,6 +5734,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("superCallAbstractClass.kt")
|
||||||
|
public void testSuperCallAbstractClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallAbstractClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("superCallInterface.kt")
|
@TestMetadata("superCallInterface.kt")
|
||||||
public void testSuperCallInterface() throws Exception {
|
public void testSuperCallInterface() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.descriptors
|
|||||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
|
|
||||||
fun ModuleDescriptor.resolveClassByFqName(fqName: FqName, lookupLocation: LookupLocation): ClassDescriptor? {
|
fun ModuleDescriptor.resolveClassByFqName(fqName: FqName, lookupLocation: LookupLocation): ClassDescriptor? {
|
||||||
@@ -38,6 +37,3 @@ fun ModuleDescriptor.findContinuationClassDescriptorOrNull(lookupLocation: Looku
|
|||||||
|
|
||||||
fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation) =
|
fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation) =
|
||||||
findContinuationClassDescriptorOrNull(lookupLocation).sure { "Continuation interface is not found" }
|
findContinuationClassDescriptorOrNull(lookupLocation).sure { "Continuation interface is not found" }
|
||||||
|
|
||||||
fun FunctionDescriptor.isEffectivelyOpen() =
|
|
||||||
modality == Modality.OPEN && containingDeclaration.safeAs<ClassDescriptor>()?.modality == Modality.OPEN
|
|
||||||
|
|||||||
@@ -6424,6 +6424,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("superCallAbstractClass.kt")
|
||||||
|
public void testSuperCallAbstractClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallAbstractClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("superCallInterface.kt")
|
@TestMetadata("superCallInterface.kt")
|
||||||
public void testSuperCallInterface() throws Exception {
|
public void testSuperCallInterface() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/superCallInterface.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user