From 9d4047f5e4fbf18ab81356efda0b09624b0c6f02 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 25 Jan 2017 16:27:49 +0300 Subject: [PATCH] Calls for suspend functions imported from object should be checked in CoroutineSuspendCallChecker. --- .../calls/checkers/coroutineCallChecker.kt | 6 ++---- .../tests/coroutines/illegalSuspendCalls.kt | 9 +++++++++ .../tests/coroutines/illegalSuspendCalls.txt | 9 +++++++++ .../tests/coroutines/nonLocalSuspension.kt | 18 ++++++++++++++++++ .../tests/coroutines/nonLocalSuspension.txt | 8 ++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt index 06fcb58bcbd..26355a92573 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt @@ -42,7 +42,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs object CoroutineSuspendCallChecker : CallChecker { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { - val descriptor = resolvedCall.candidateDescriptor as? SimpleFunctionDescriptor ?: return + val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return if (!descriptor.isSuspend) return val enclosingSuspendFunction = @@ -60,9 +60,7 @@ object CoroutineSuspendCallChecker : CallChecker { context.trace.report(Errors.NON_LOCAL_SUSPENSION_POINT.on(reportOn)) } - context.trace.record( - BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction - ) + context.trace.record(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction) checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context) } diff --git a/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.kt b/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.kt index eddaa3c96a3..68e32270b16 100644 --- a/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.kt +++ b/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.kt @@ -1,13 +1,22 @@ +import Host.bar + +object Host { + suspend fun bar() {} +} + suspend fun foo() {} fun noSuspend() { foo() + bar() } class A { init { foo() + bar() } } val x = foo() +val y = bar() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.txt b/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.txt index 5e94d2d7c4e..cce5721c9e6 100644 --- a/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.txt +++ b/compiler/testData/diagnostics/tests/coroutines/illegalSuspendCalls.txt @@ -1,6 +1,7 @@ package public val x: kotlin.Unit +public val y: kotlin.Unit public suspend fun foo(): kotlin.Unit public fun noSuspend(): kotlin.Unit @@ -10,3 +11,11 @@ public final class A { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public object Host { + private constructor Host() + public final suspend fun bar(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.kt b/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.kt index 8a81b8f9c03..82d02532f2f 100644 --- a/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.kt +++ b/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.kt @@ -1,8 +1,13 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER +import Host.suspendFromObject suspend fun suspendHere() = 1 suspend fun another(a: T) = 1 +object Host { + suspend fun suspendFromObject() = 1 +} + fun builder(c: suspend () -> Unit) { } inline fun run(x: () -> Unit) {} @@ -15,46 +20,59 @@ fun foo() { var result = 1 builder { suspendHere() + suspendFromObject() + another("") another(1) result += suspendHere() + result += suspendFromObject() run { result += suspendHere() + result += suspendFromObject() + run { suspendHere() + suspendFromObject() } } runCross { result += suspendHere() + result += suspendFromObject() runCross { suspendHere() + suspendFromObject() } } noinline { result += suspendHere() + result += suspendFromObject() noinline { suspendHere() + suspendFromObject() } } class A { fun bar() { suspendHere() + suspendFromObject() } } object : Any() { fun baz() { suspendHere() + suspendFromObject() } } builder { suspendHere() + suspendFromObject() another(1) another("") diff --git a/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.txt b/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.txt index 034bd5d1b4d..903cf5b2230 100644 --- a/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.txt +++ b/compiler/testData/diagnostics/tests/coroutines/nonLocalSuspension.txt @@ -7,3 +7,11 @@ public fun noinline(/*0*/ x: () -> kotlin.Unit): kotlin.Unit public inline fun run(/*0*/ x: () -> kotlin.Unit): kotlin.Unit public inline fun runCross(/*0*/ crossinline x: () -> kotlin.Unit): kotlin.Unit public suspend fun suspendHere(): kotlin.Int + +public object Host { + private constructor Host() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final suspend fun suspendFromObject(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +}