Report error when suspend call is illegal in the scope

Namely when it's not contained inside coroutine or another suspend function

 #KT-14924 In Progress
This commit is contained in:
Denis Zharkov
2016-11-30 14:59:58 +03:00
parent 240d82d167
commit aa50f1d824
6 changed files with 38 additions and 2 deletions
@@ -862,6 +862,7 @@ public interface Errors {
DiagnosticFactory0<PsiElement> NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> ILLEGAL_SUSPEND_FUNCTION_CALL = DiagnosticFactory0.create(ERROR);
// Error sets
@@ -820,6 +820,7 @@ public class DefaultErrorMessages {
MAP.put(INLINE_CALL_CYCLE, "The ''{0}'' invocation is a part of inline cycle", NAME);
MAP.put(NON_LOCAL_RETURN_IN_DISABLED_INLINE, "Non-local returns are not allowed with inlining disabled");
MAP.put(NON_LOCAL_SUSPENSION_POINT, "Suspension functions can be called only within coroutine body");
MAP.put(ILLEGAL_SUSPEND_FUNCTION_CALL, "Suspend functions are only allowed to be called from a coroutine or another suspend function");
MAP.setImmutable();
@@ -47,11 +47,11 @@ object CoroutineSuspendCallChecker : CallChecker {
when {
enclosingSuspendFunction != null -> {
// TODO: check if tail call
// Tail calls checks happen during control flow analysis
// Here we only record enclosing function mapping (for backends purposes)
context.trace.record(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.call, enclosingSuspendFunction)
}
closestCoroutineReceiver != null -> {
val callElement = resolvedCall.call.callElement as KtExpression
if (!InlineUtil.checkNonLocalReturnUsage(closestCoroutineReceiver.declarationDescriptor, callElement, context.resolutionContext)) {
@@ -60,6 +60,9 @@ object CoroutineSuspendCallChecker : CallChecker {
context.trace.record(BindingContext.COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, resolvedCall.call, closestCoroutineReceiver)
}
else -> {
context.trace.report(Errors.ILLEGAL_SUSPEND_FUNCTION_CALL.on(reportOn))
}
}
}
}