Fix improper handling of coroutine interceptors

Don't use coroutine facade in following cases:
* When calling coroutine functions in non-suspend mode (i.e.
  suspend flag is either false or skipped).
* When passing continuation from suspend function to suspend function.

Use facade only for corresponding intrinsics.
Reason: interceptor should not be called on each suspend function
invocation, it should be called after resume from innermost
suspend function.

Fix KT-17067. The example provided with the issue is very similar to
dispatchResume.kt which passes after these changes.

Add test to prove that KT-17446 is no more reproducible.
This commit is contained in:
Alexey Andreev
2017-04-13 12:40:09 +03:00
parent f3ed75998e
commit 7e6df03421
15 changed files with 91 additions and 36 deletions
@@ -161,7 +161,7 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
functionWithBody.parameters += JsParameter(suspendedName)
val instanceName = functionWithBody.scope.declareFreshName("instance")
functionWithBody.body.statements += JsAstUtils.newVar(instanceName, JsNameRef(context.metadata.facadeName, instantiation))
functionWithBody.body.statements += JsAstUtils.newVar(instanceName, instantiation)
val invokeResume = JsReturn(JsInvocation(JsNameRef(context.metadata.doResumeName, instanceName.makeRef()), JsLiteral.NULL))
@@ -213,12 +213,10 @@ public class JsInliner extends JsVisitorWithContextImpl {
}
private void inlineSuspendWithCurrentContinuation(@NotNull JsInvocation call, @NotNull JsContext context) {
JsInliningContext inliningContext = getInliningContext();
JsFunction containingFunction = inliningContext.function;
JsExpression lambda = call.getArguments().get(0);
JsParameter continuationParam = containingFunction.getParameters().get(containingFunction.getParameters().size() - 1);
JsExpression continuationArg = call.getArguments().get(call.getArguments().size() - 1);
JsInvocation invocation = new JsInvocation(lambda, continuationParam.getName().makeRef());
JsInvocation invocation = new JsInvocation(lambda, continuationArg);
MetadataProperties.setSuspend(invocation, true);
context.replaceMe(accept(invocation));
}
@@ -268,11 +266,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
private class JsInliningContext implements InliningContext {
private final FunctionContext functionContext;
@NotNull
public final JsFunction function;
JsInliningContext(@NotNull JsFunction function) {
this.function = function;
functionContext = new FunctionContext(function, functionReader) {
@Nullable
@Override