Support new suspend convention in JVM backend partially
Stack-unwinding does not work yet #KT-14924 In Progress
This commit is contained in:
@@ -78,6 +78,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
|||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
|
||||||
|
import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||||
@@ -1900,15 +1901,29 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue genCoroutineInstanceValueFromResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
public StackValue genCoroutineInstanceValueFromResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
ExtensionReceiver controllerReceiver = getControllerReceiverFromResolvedCall(resolvedCall);
|
return getCoroutineInstanceValueByReceiver(getControllerReceiverFromResolvedCall(resolvedCall));
|
||||||
ClassDescriptor coroutineClassDescriptor =
|
}
|
||||||
bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, controllerReceiver.getDeclarationDescriptor());
|
|
||||||
assert coroutineClassDescriptor != null : "Coroutine class descriptor should not be null";
|
|
||||||
|
|
||||||
// second argument for handleResult is always Continuation<T> ('this'-object in current implementation)
|
@NotNull
|
||||||
|
private StackValue getCoroutineInstanceValueByReceiver(
|
||||||
|
@NotNull ExtensionReceiver descriptor
|
||||||
|
) {
|
||||||
|
ClassDescriptor coroutineClassDescriptor =
|
||||||
|
bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, descriptor.getDeclarationDescriptor());
|
||||||
|
assert coroutineClassDescriptor != null : "Coroutine class descriptor should not be null";
|
||||||
return StackValue.thisOrOuter(this, coroutineClassDescriptor, false, false);
|
return StackValue.thisOrOuter(this, coroutineClassDescriptor, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private StackValue getCoroutineInstanceValueForSuspensionPoint(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
|
CoroutineReceiverValue coroutineReceiverValue =
|
||||||
|
bindingContext.get(COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, resolvedCall.getCall());
|
||||||
|
|
||||||
|
if (coroutineReceiverValue == null) return null;
|
||||||
|
|
||||||
|
return getCoroutineInstanceValueByReceiver(coroutineReceiverValue);
|
||||||
|
}
|
||||||
|
|
||||||
private static ExtensionReceiver getControllerReceiverFromResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
private static ExtensionReceiver getControllerReceiverFromResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
ReceiverValue controllerReceiver =
|
ReceiverValue controllerReceiver =
|
||||||
resolvedCall.getDispatchReceiver() != null
|
resolvedCall.getDispatchReceiver() != null
|
||||||
@@ -2515,7 +2530,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int lookupLocalIndex(DeclarationDescriptor descriptor) {
|
public int lookupLocalIndex(DeclarationDescriptor descriptor) {
|
||||||
return myFrameMap.getIndex(descriptor);
|
return myFrameMap.getIndex(getParameterSynonymOrThis(descriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeclarationDescriptor getParameterSynonymOrThis(DeclarationDescriptor descriptor) {
|
||||||
|
if (!(descriptor instanceof ValueParameterDescriptor)) return descriptor;
|
||||||
|
|
||||||
|
DeclarationDescriptor synonym = bindingContext.get(CodegenBinding.PARAMETER_SYNONYM, (ValueParameterDescriptor) descriptor);
|
||||||
|
return synonym != null ? synonym : descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -2754,9 +2776,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@NotNull
|
@NotNull
|
||||||
public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
|
public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
|
||||||
ResolvedCallWithRealDescriptor callWithRealDescriptor =
|
ResolvedCallWithRealDescriptor callWithRealDescriptor =
|
||||||
CoroutineCodegenUtilKt.replaceSuspensionFunctionViewWithRealDescriptor(resolvedCall, state.getProject());
|
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(
|
||||||
|
resolvedCall, state.getProject(), state.getBindingContext()
|
||||||
|
);
|
||||||
if (callWithRealDescriptor != null) {
|
if (callWithRealDescriptor != null) {
|
||||||
tempVariables.put(callWithRealDescriptor.getFakeThisExpression(), genCoroutineInstanceValueFromResolvedCall(resolvedCall));
|
StackValue coroutineInstanceValueForSuspensionPoint = getCoroutineInstanceValueForSuspensionPoint(resolvedCall);
|
||||||
|
StackValue coroutineInstanceValue =
|
||||||
|
coroutineInstanceValueForSuspensionPoint != null
|
||||||
|
? coroutineInstanceValueForSuspensionPoint
|
||||||
|
: getContinuationParameterFromEnclosingSuspendFunction(resolvedCall);
|
||||||
|
tempVariables.put(callWithRealDescriptor.getFakeContinuationExpression(), coroutineInstanceValue);
|
||||||
|
|
||||||
return invokeFunction(callWithRealDescriptor.getResolvedCall(), receiver);
|
return invokeFunction(callWithRealDescriptor.getResolvedCall(), receiver);
|
||||||
}
|
}
|
||||||
FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall);
|
FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall);
|
||||||
@@ -2778,7 +2808,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this);
|
||||||
|
|
||||||
if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall)) {
|
if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) {
|
||||||
// Suspension points should behave like they leave actual values on stack, while real methods return VOID
|
// Suspension points should behave like they leave actual values on stack, while real methods return VOID
|
||||||
return new OperationStackValue(getSuspensionReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda());
|
return new OperationStackValue(getSuspensionReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda());
|
||||||
}
|
}
|
||||||
@@ -2786,6 +2816,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private StackValue getContinuationParameterFromEnclosingSuspendFunction(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
|
SimpleFunctionDescriptor enclosingSuspendFunction =
|
||||||
|
bindingContext.get(BindingContext.ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall());
|
||||||
|
|
||||||
|
assert enclosingSuspendFunction != null
|
||||||
|
: "Suspend functions may be called either as suspension points or from another suspend function";
|
||||||
|
|
||||||
|
SimpleFunctionDescriptor enclosingSuspendFunctionJvmView =
|
||||||
|
bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, enclosingSuspendFunction);
|
||||||
|
|
||||||
|
assert enclosingSuspendFunctionJvmView != null : "No JVM view function found for " + enclosingSuspendFunction;
|
||||||
|
|
||||||
|
ValueParameterDescriptor continuationParameter =
|
||||||
|
enclosingSuspendFunctionJvmView.getValueParameters()
|
||||||
|
.get(enclosingSuspendFunctionJvmView.getValueParameters().size() - 1);
|
||||||
|
|
||||||
|
return findLocalOrCapturedValue(continuationParameter);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
// Find the first parent of the current context which corresponds to a subclass of a given class
|
// Find the first parent of the current context which corresponds to a subclass of a given class
|
||||||
public static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
|
public static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) {
|
||||||
@@ -2838,7 +2887,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@NotNull CallGenerator callGenerator,
|
@NotNull CallGenerator callGenerator,
|
||||||
@NotNull ArgumentGenerator argumentGenerator
|
@NotNull ArgumentGenerator argumentGenerator
|
||||||
) {
|
) {
|
||||||
boolean isSuspensionPoint = CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall);
|
boolean isSuspensionPoint = CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext);
|
||||||
if (isSuspensionPoint) {
|
if (isSuspensionPoint) {
|
||||||
// Inline markers are used to spill the stack before coroutine suspension
|
// Inline markers are used to spill the stack before coroutine suspension
|
||||||
addInlineMarker(v, true);
|
addInlineMarker(v, true);
|
||||||
@@ -2876,11 +2925,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isSuspensionPoint) {
|
if (isSuspensionPoint) {
|
||||||
v.aconst(getSuspensionReturnTypeByResolvedCall(resolvedCall).getDescriptor());
|
v.tconst(getSuspensionReturnTypeByResolvedCall(resolvedCall));
|
||||||
v.invokestatic(
|
v.invokestatic(
|
||||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
||||||
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
||||||
"(Ljava/lang/String;)V", false);
|
"(Ljava/lang/Class;)V", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||||
@@ -2905,8 +2954,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor
|
assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor
|
||||||
: "Suspension point resolved call should be built on SimpleFunctionDescriptor";
|
: "Suspension point resolved call should be built on SimpleFunctionDescriptor";
|
||||||
|
|
||||||
KotlinType returnType = org.jetbrains.kotlin.resolve.coroutine.CoroutineUtilKt
|
FunctionDescriptor initialSignature =
|
||||||
.getSuspensionPointReturnType((SimpleFunctionDescriptor) resolvedCall.getResultingDescriptor());
|
((SimpleFunctionDescriptor) resolvedCall.getResultingDescriptor())
|
||||||
|
.getUserData(CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION);
|
||||||
|
|
||||||
|
assert initialSignature != null : "Initial signature must be not null for suspension point";
|
||||||
|
|
||||||
|
KotlinType returnType = initialSignature.getReturnType();
|
||||||
|
|
||||||
assert returnType != null : "Return type of suspension point should not be null";
|
assert returnType != null : "Return type of suspension point should not be null";
|
||||||
return typeMapper.mapType(returnType);
|
return typeMapper.mapType(returnType);
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.ArrayUtil;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.collections.CollectionsKt;
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import kotlin.text.StringsKt;
|
import kotlin.text.StringsKt;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
|
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
|
||||||
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
|
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
@@ -81,9 +82,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
||||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isAnnotationOrJvm6Interface;
|
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8Interface;
|
|
||||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceMember;
|
|
||||||
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.annotations.AnnotationUseSiteTarget.*;
|
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
||||||
@@ -128,6 +127,10 @@ public class FunctionCodegen {
|
|||||||
throw ExceptionLogger.logDescriptorNotFound("No descriptor for function " + function.getName(), function);
|
throw ExceptionLogger.logDescriptorNotFound("No descriptor for function " + function.getName(), function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, functionDescriptor) != null) {
|
||||||
|
functionDescriptor = bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, functionDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) {
|
if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) {
|
||||||
generateMethod(JvmDeclarationOriginKt.OtherOrigin(function, functionDescriptor), functionDescriptor,
|
generateMethod(JvmDeclarationOriginKt.OtherOrigin(function, functionDescriptor), functionDescriptor,
|
||||||
new FunctionGenerationStrategy.FunctionDefault(state, function));
|
new FunctionGenerationStrategy.FunctionDefault(state, function));
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.continuationClassDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.hasNoinlineInterceptResume
|
import org.jetbrains.kotlin.codegen.coroutines.hasNoinlineInterceptResume
|
||||||
import org.jetbrains.kotlin.coroutines.controllerTypeIfCoroutine
|
import org.jetbrains.kotlin.coroutines.controllerTypeIfCoroutine
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -24,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.createFunctionType
|
import org.jetbrains.kotlin.resolve.calls.util.createFunctionType
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -59,7 +59,7 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
|
|||||||
* @return `Continuation<Any?>` type
|
* @return `Continuation<Any?>` type
|
||||||
*/
|
*/
|
||||||
private fun createNullableAnyContinuation(module: ModuleDescriptor): KotlinType {
|
private fun createNullableAnyContinuation(module: ModuleDescriptor): KotlinType {
|
||||||
val classDescriptor = module.builtIns.getBuiltInClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME)
|
val classDescriptor = module.builtIns.continuationClassDescriptor
|
||||||
|
|
||||||
return TypeConstructorSubstitution.createByParametersMap(
|
return TypeConstructorSubstitution.createByParametersMap(
|
||||||
mapOf(classDescriptor.declaredTypeParameters.single() to TypeProjectionImpl(module.builtIns.nullableAnyType))
|
mapOf(classDescriptor.declaredTypeParameters.single() to TypeProjectionImpl(module.builtIns.nullableAnyType))
|
||||||
|
|||||||
+29
@@ -20,6 +20,8 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.tree.TokenSet;
|
import com.intellij.psi.tree.TokenSet;
|
||||||
import com.intellij.util.containers.Stack;
|
import com.intellij.util.containers.Stack;
|
||||||
|
import kotlin.Pair;
|
||||||
|
import kotlin.collections.CollectionsKt;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -432,6 +434,33 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
// working around a problem with shallow analysis
|
// working around a problem with shallow analysis
|
||||||
if (functionDescriptor == null) return;
|
if (functionDescriptor == null) return;
|
||||||
|
|
||||||
|
if (functionDescriptor instanceof SimpleFunctionDescriptor && functionDescriptor.isSuspend()) {
|
||||||
|
SimpleFunctionDescriptor jvmSuspendFunctionView =
|
||||||
|
CoroutineCodegenUtilKt.createJvmSuspendFunctionView(
|
||||||
|
(SimpleFunctionDescriptor) functionDescriptor
|
||||||
|
);
|
||||||
|
|
||||||
|
// This is a very subtle place (hack).
|
||||||
|
// When generating bytecode of some suspend function, we replace the original descriptor
|
||||||
|
// with one that reflects how it should look on JVM.
|
||||||
|
// But the problem is that the function may contain resolved calls referencing original parameters, that are recreated
|
||||||
|
// in jvmSuspendFunctionView.
|
||||||
|
// So we remember the relation between the old and the new parameter descriptors and use it when looking for their indices
|
||||||
|
// in ExpressionCodegen.
|
||||||
|
for (Pair<ValueParameterDescriptor, ValueParameterDescriptor> parameterDescriptorPair : CollectionsKt
|
||||||
|
.zip(functionDescriptor.getValueParameters(), jvmSuspendFunctionView.getValueParameters())) {
|
||||||
|
bindingTrace.record(
|
||||||
|
CodegenBinding.PARAMETER_SYNONYM, parameterDescriptorPair.getFirst(), parameterDescriptorPair.getSecond()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingTrace.record(
|
||||||
|
CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW,
|
||||||
|
(SimpleFunctionDescriptor) functionDescriptor,
|
||||||
|
jvmSuspendFunctionView
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
String nameForClassOrPackageMember = getNameForClassOrPackageMember(functionDescriptor);
|
String nameForClassOrPackageMember = getNameForClassOrPackageMember(functionDescriptor);
|
||||||
if (nameForClassOrPackageMember != null) {
|
if (nameForClassOrPackageMember != null) {
|
||||||
nameStack.push(nameForClassOrPackageMember);
|
nameStack.push(nameForClassOrPackageMember);
|
||||||
|
|||||||
@@ -71,6 +71,12 @@ public class CodegenBinding {
|
|||||||
public static final WritableSlice<KtElement, FunctionGenerationStrategy> CUSTOM_STRATEGY_FOR_INLINE_LAMBDA = Slices.createSimpleSlice();
|
public static final WritableSlice<KtElement, FunctionGenerationStrategy> CUSTOM_STRATEGY_FOR_INLINE_LAMBDA = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<KtElement, FunctionDescriptor> CUSTOM_DESCRIPTOR_FOR_INLINE_LAMBDA = Slices.createSimpleSlice();
|
public static final WritableSlice<KtElement, FunctionDescriptor> CUSTOM_DESCRIPTOR_FOR_INLINE_LAMBDA = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
public static final WritableSlice<SimpleFunctionDescriptor, SimpleFunctionDescriptor> SUSPEND_FUNCTION_TO_JVM_VIEW =
|
||||||
|
Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
public static final WritableSlice<ValueParameterDescriptor, ValueParameterDescriptor> PARAMETER_SYNONYM =
|
||||||
|
Slices.createSimpleSlice();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
|
BasicWritableSlice.initSliceDebugNames(CodegenBinding.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.JvmCodegenUtil;
|
|||||||
import org.jetbrains.kotlin.codegen.OwnerKind;
|
import org.jetbrains.kotlin.codegen.OwnerKind;
|
||||||
import org.jetbrains.kotlin.codegen.StackValue;
|
import org.jetbrains.kotlin.codegen.StackValue;
|
||||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
@@ -79,7 +80,10 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public StackValue generateReceiver(@NotNull CallableDescriptor descriptor, @NotNull GenerationState state, boolean ignoreNoOuter) {
|
public StackValue generateReceiver(@NotNull CallableDescriptor descriptor, @NotNull GenerationState state, boolean ignoreNoOuter) {
|
||||||
if (getCallableDescriptorWithReceiver() == descriptor) {
|
// When generating bytecode of some suspend function, we replace the original descriptor with one that reflects how it should look on JVM.
|
||||||
|
// But when we looking for receiver parameter in resolved call, it still references the initial function, so we unwrap it here
|
||||||
|
// before comparision.
|
||||||
|
if (CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(getCallableDescriptorWithReceiver()) == descriptor) {
|
||||||
return getReceiverExpression(state.getTypeMapper());
|
return getReceiverExpression(state.getTypeMapper());
|
||||||
}
|
}
|
||||||
ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
|
ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
|
||||||
|
|||||||
+1
-1
@@ -171,7 +171,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
suspensionCallBegin = beforeSuspensionPointMarker,
|
suspensionCallBegin = beforeSuspensionPointMarker,
|
||||||
suspensionCallEnd = methodInsn,
|
suspensionCallEnd = methodInsn,
|
||||||
fakeReturnValueInsns = fakeReturnValueInsns,
|
fakeReturnValueInsns = fakeReturnValueInsns,
|
||||||
returnType = Type.getType((beforeSuspensionPointMarker.previous as LdcInsnNode).cst as String))
|
returnType = (beforeSuspensionPointMarker.previous as LdcInsnNode).cst as Type)
|
||||||
suspensionPoints.add(suspensionPoint)
|
suspensionPoints.add(suspensionPoint)
|
||||||
|
|
||||||
// Drop type info from marker
|
// Drop type info from marker
|
||||||
|
|||||||
+114
-26
@@ -17,13 +17,19 @@
|
|||||||
package org.jetbrains.kotlin.codegen.coroutines
|
package org.jetbrains.kotlin.codegen.coroutines
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingTraceContext
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments
|
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
@@ -32,13 +38,16 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||||
import org.jetbrains.kotlin.resolve.coroutine.REPLACED_SUSPENSION_POINT_KEY
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.coroutine.SUSPENSION_POINT_KEY
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
|
|
||||||
// These classes do not actually exist at runtime
|
// These classes do not actually exist at runtime
|
||||||
val CONTINUATION_METHOD_ANNOTATION_DESC = "Lkotlin/ContinuationMethod;"
|
val CONTINUATION_METHOD_ANNOTATION_DESC = "Lkotlin/ContinuationMethod;"
|
||||||
@@ -54,30 +63,26 @@ const val COROUTINE_CONTROLLER_FIELD_NAME = "_controller"
|
|||||||
const val COROUTINE_CONTROLLER_GETTER_NAME = "getController"
|
const val COROUTINE_CONTROLLER_GETTER_NAME = "getController"
|
||||||
const val COROUTINE_LABEL_FIELD_NAME = "label"
|
const val COROUTINE_LABEL_FIELD_NAME = "label"
|
||||||
|
|
||||||
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeThisExpression: KtExpression)
|
data class ResolvedCallWithRealDescriptor(val resolvedCall: ResolvedCall<*>, val fakeContinuationExpression: KtExpression)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION = object : FunctionDescriptor.UserDataKey<FunctionDescriptor> {}
|
||||||
// Resolved calls to suspension function contain descriptors as they visible within coroutines:
|
// Resolved calls to suspension function contain descriptors as they visible within coroutines:
|
||||||
// E.g. `fun <V> await(f: CompletableFuture<V>): V` instead of `fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>): Unit`
|
// E.g. `fun <V> await(f: CompletableFuture<V>): V` instead of `fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>): Unit`
|
||||||
// See `createCoroutineSuspensionFunctionView` and it's usages for clarification
|
// See `createJvmSuspendFunctionView` and it's usages for clarification
|
||||||
// But for call generation it's convenient to have `machine` (continuation) parameter/argument within resolvedCall.
|
// But for call generation it's convenient to have `machine` (continuation) parameter/argument within resolvedCall.
|
||||||
// So this function returns resolved call with descriptor looking like `fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>): Unit`
|
// So this function returns resolved call with descriptor looking like `fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>): Unit`
|
||||||
// and fake `this` expression that used as argument for second parameter
|
// and fake `this` expression that used as argument for second parameter
|
||||||
fun ResolvedCall<*>.replaceSuspensionFunctionViewWithRealDescriptor(
|
fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
|
||||||
project: Project
|
project: Project,
|
||||||
|
bindingContext: BindingContext
|
||||||
): ResolvedCallWithRealDescriptor? {
|
): ResolvedCallWithRealDescriptor? {
|
||||||
val function = candidateDescriptor as? FunctionDescriptor ?: return null
|
val function = candidateDescriptor as? SimpleFunctionDescriptor ?: return null
|
||||||
if (!isSuspensionPoint()) return null
|
if (!function.isSuspend || function.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) return null
|
||||||
|
|
||||||
val initialSignatureDescriptor = function.initialSignatureDescriptor ?: return null
|
|
||||||
if (function.getUserData(REPLACED_SUSPENSION_POINT_KEY) == true) return null
|
|
||||||
|
|
||||||
val newCandidateDescriptor =
|
val newCandidateDescriptor =
|
||||||
initialSignatureDescriptor.createCustomCopy {
|
bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, function)
|
||||||
setPreserveSourceElement()
|
?: createJvmSuspendFunctionView(function)
|
||||||
setSignatureChange()
|
|
||||||
putUserData(SUSPENSION_POINT_KEY, true)
|
|
||||||
putUserData(REPLACED_SUSPENSION_POINT_KEY, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
val newCall = ResolvedCallImpl(
|
val newCall = ResolvedCallImpl(
|
||||||
call,
|
call,
|
||||||
@@ -180,13 +185,35 @@ fun createResolvedCallForInterceptResume(
|
|||||||
return InterceptResumeCallContext(resolvedCall, thisExpression)
|
return InterceptResumeCallContext(resolvedCall, thisExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ResolvedCall<*>.isSuspensionPoint() =
|
fun ResolvedCall<*>.isSuspensionPoint(bindingContext: BindingContext) =
|
||||||
(candidateDescriptor as? FunctionDescriptor)?.let { it.isSuspend && it.getUserData(SUSPENSION_POINT_KEY) ?: false }
|
bindingContext[BindingContext.COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, call] != null
|
||||||
?: false
|
|
||||||
|
|
||||||
private fun FunctionDescriptor.createCustomCopy(
|
// Suspend functions have irregular signatures on JVM, containing an additional last parameter with type `Continuation<return-type>`,
|
||||||
copySettings: FunctionDescriptor.CopyBuilder<out FunctionDescriptor>.(FunctionDescriptor) -> FunctionDescriptor.CopyBuilder<out FunctionDescriptor>
|
// and return type Unit (later it will be replaced with 'Any?')
|
||||||
): FunctionDescriptor {
|
// This function returns a function descriptor reflecting how the suspend function looks from point of view of JVM
|
||||||
|
fun <D : FunctionDescriptor> createJvmSuspendFunctionView(function: D): D {
|
||||||
|
val continuationParameter = ValueParameterDescriptorImpl(
|
||||||
|
function, null, function.valueParameters.size, Annotations.EMPTY, Name.identifier("\$continuation"),
|
||||||
|
function.getContinuationParameterTypeOfSuspendFunction(),
|
||||||
|
/* declaresDefaultValue = */ false, /* isCrossinline = */ false,
|
||||||
|
/* isNoinline = */ false, /* isCoroutine = */ false, /* varargElementType = */ null, SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
|
||||||
|
return function.createCustomCopy {
|
||||||
|
setPreserveSourceElement()
|
||||||
|
setReturnType(function.builtIns.unitType)
|
||||||
|
setValueParameters(it.valueParameters + continuationParameter)
|
||||||
|
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder =
|
||||||
|
FunctionDescriptor.CopyBuilder<out FunctionDescriptor>.(FunctionDescriptor)
|
||||||
|
-> FunctionDescriptor.CopyBuilder<out FunctionDescriptor>
|
||||||
|
|
||||||
|
private fun <D : FunctionDescriptor> D.createCustomCopy(
|
||||||
|
copySettings: FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder
|
||||||
|
): D {
|
||||||
|
|
||||||
val newOriginal =
|
val newOriginal =
|
||||||
if (original !== this)
|
if (original !== this)
|
||||||
@@ -198,9 +225,18 @@ private fun FunctionDescriptor.createCustomCopy(
|
|||||||
|
|
||||||
result.overriddenDescriptors = this.overriddenDescriptors.map { it.createCustomCopy(copySettings) }
|
result.overriddenDescriptors = this.overriddenDescriptors.map { it.createCustomCopy(copySettings) }
|
||||||
|
|
||||||
return result
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return result as D
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() =
|
||||||
|
KotlinTypeFactory.simpleType(
|
||||||
|
builtIns.continuationClassDescriptor.defaultType,
|
||||||
|
arguments = listOf(returnType!!.asTypeProjection())
|
||||||
|
)
|
||||||
|
|
||||||
|
val KotlinBuiltIns.continuationClassDescriptor get() = getBuiltInClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME)
|
||||||
|
|
||||||
fun KotlinType.hasInlineInterceptResume() =
|
fun KotlinType.hasInlineInterceptResume() =
|
||||||
findOperatorInController(this, OperatorNameConventions.COROUTINE_INTERCEPT_RESUME)?.isInline == true
|
findOperatorInController(this, OperatorNameConventions.COROUTINE_INTERCEPT_RESUME)?.isInline == true
|
||||||
|
|
||||||
@@ -209,3 +245,55 @@ fun KotlinType.hasNoinlineInterceptResume() =
|
|||||||
|
|
||||||
fun findOperatorInController(controllerType: KotlinType, name: Name): SimpleFunctionDescriptor? =
|
fun findOperatorInController(controllerType: KotlinType, name: Name): SimpleFunctionDescriptor? =
|
||||||
controllerType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull { it.isOperator }
|
controllerType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull { it.isOperator }
|
||||||
|
|
||||||
|
val SUSPEND_WITH_CURRENT_CONTINUATION_NAME = Name.identifier("suspendWithCurrentContinuation")
|
||||||
|
|
||||||
|
fun FunctionDescriptor.isBuiltInSuspendWithCurrentContinuation(): Boolean {
|
||||||
|
if (name != SUSPEND_WITH_CURRENT_CONTINUATION_NAME) return false
|
||||||
|
|
||||||
|
val originalDeclaration =
|
||||||
|
builtIns.builtInsPackageFragments.singleOrNull { it.fqName == KotlinBuiltIns.COROUTINES_PACKAGE_FQ_NAME }
|
||||||
|
?.getMemberScope()
|
||||||
|
?.getContributedFunctions(SUSPEND_WITH_CURRENT_CONTINUATION_NAME, NoLookupLocation.FROM_BACKEND)
|
||||||
|
?.singleOrNull()
|
||||||
|
?: return false
|
||||||
|
|
||||||
|
return DescriptorEquivalenceForOverrides.areEquivalent(
|
||||||
|
originalDeclaration, this.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createMethodNodeForSuspendWithCurrentContinuation(
|
||||||
|
functionDescriptor: FunctionDescriptor,
|
||||||
|
typeMapper: KotlinTypeMapper
|
||||||
|
): MethodNode {
|
||||||
|
assert(functionDescriptor.isBuiltInSuspendWithCurrentContinuation()) {
|
||||||
|
"functionDescriptor must be kotlin.coroutines.suspendWithCurrentContinuation"
|
||||||
|
}
|
||||||
|
|
||||||
|
val node =
|
||||||
|
MethodNode(
|
||||||
|
Opcodes.ASM5,
|
||||||
|
Opcodes.ACC_STATIC,
|
||||||
|
"fake",
|
||||||
|
typeMapper.mapAsmMethod(functionDescriptor).descriptor, null, null
|
||||||
|
)
|
||||||
|
|
||||||
|
node.visitVarInsn(Opcodes.ALOAD, 0)
|
||||||
|
node.visitVarInsn(Opcodes.ALOAD, 1)
|
||||||
|
node.visitMethodInsn(
|
||||||
|
Opcodes.INVOKEINTERFACE,
|
||||||
|
typeMapper.mapType(functionDescriptor.valueParameters[0]).internalName,
|
||||||
|
OperatorNameConventions.INVOKE.identifier,
|
||||||
|
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
node.visitInsn(Opcodes.POP)
|
||||||
|
node.visitInsn(Opcodes.RETURN)
|
||||||
|
node.visitMaxs(2, 2)
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CallableDescriptor?.unwrapInitialDescriptorForSuspendFunction() =
|
||||||
|
(this as? SimpleFunctionDescriptor)?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) ?: this
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment;
|
|||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
|
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
@@ -246,6 +247,14 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
);
|
);
|
||||||
return new SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1));
|
return new SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1));
|
||||||
}
|
}
|
||||||
|
else if (CoroutineCodegenUtilKt.isBuiltInSuspendWithCurrentContinuation(functionDescriptor)) {
|
||||||
|
return new SMAPAndMethodNode(
|
||||||
|
CoroutineCodegenUtilKt.createMethodNodeForSuspendWithCurrentContinuation(
|
||||||
|
functionDescriptor, codegen.getState().getTypeMapper()
|
||||||
|
),
|
||||||
|
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final GenerationState state = codegen.getState();
|
final GenerationState state = codegen.getState();
|
||||||
final Method asmMethod =
|
final Method asmMethod =
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class Controller {
|
|||||||
exception = t
|
exception = t
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendHere(x: Continuation<Any>) {}
|
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Any>) {}
|
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class Controller {
|
|||||||
result = "OK"
|
result = "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun <T> await(t: T, c: Continuation<T>) {
|
suspend fun <T> await(t: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(t)
|
c.resume(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendAndLog(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "suspend($value);"
|
result += "suspend($value);"
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "["
|
result += "["
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendAndLog(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "suspend($value);"
|
result += "suspend($value);"
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendLogAndThrow(exception: Throwable, c: Continuation<Nothing>) {
|
suspend fun suspendLogAndThrow(exception: Throwable): Nothing = suspendWithCurrentContinuation { c ->
|
||||||
result += "throw(${exception.message});"
|
result += "throw(${exception.message});"
|
||||||
c.resumeWithException(exception)
|
c.resumeWithException(exception)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendAndLog(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "suspend($value);"
|
result += "suspend($value);"
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
@@ -35,4 +35,4 @@ fun box(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T, c: Continuation<T>) {
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = false
|
var result = false
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(a: String = "abc", i: Int = 2, x: Continuation<String>) {
|
suspend fun suspendHere(a: String = "abc", i: Int = 2): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(a + "#" + (i + 1))
|
x.resume(a + "#" + (i + 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
var result = 0
|
var result = 0
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
result++
|
result++
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun <T> suspendHere(v: T, x: Continuation<T>) {
|
suspend fun <T> suspendHere(v: T): T = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ class GeneratorController<T>() : AbstractIterator<T>() {
|
|||||||
this.nextStep = step
|
this.nextStep = step
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun yield(value: T, c: Continuation<Unit>) {
|
suspend fun yield(value: T): Unit = suspendWithCurrentContinuation { c ->
|
||||||
setNext(value)
|
setNext(value)
|
||||||
setNextStep(c)
|
setNextStep(c)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ class Controller {
|
|||||||
var exception: Throwable? = null
|
var exception: Throwable? = null
|
||||||
val postponedActions = ArrayList<() -> Unit>()
|
val postponedActions = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var isCompleted = false
|
var isCompleted = false
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var log = ""
|
var log = ""
|
||||||
|
|
||||||
suspend fun <T> suspendAndLog(value: T, x: Continuation<T>) {
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { x ->
|
||||||
log += "suspend($value);"
|
log += "suspend($value);"
|
||||||
x.resume(value)
|
x.resume(value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// NO_INTERCEPT_RESUME_TESTS
|
// NO_INTERCEPT_RESUME_TESTS
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,17 +8,13 @@ class Controller {
|
|||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun suspendInline(v: String, x: Continuation<String>) {
|
suspend inline fun suspendInline(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
withValue(v, x)
|
withValue(v, x)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun suspendInline(crossinline b: () -> String, x: Continuation<String>) {
|
suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b())
|
||||||
suspendInline(b(), x)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend inline fun <reified T : Any> suspendInline(x: Continuation<String>) {
|
suspend inline fun <reified T : Any> suspendInline(): String = suspendInline({ T::class.simpleName!! })
|
||||||
suspendInline({ T::class.simpleName!! }, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ var wasCalled = false
|
|||||||
class Controller {
|
class Controller {
|
||||||
val postponedActions = mutableListOf<() -> Unit>()
|
val postponedActions = mutableListOf<() -> Unit>()
|
||||||
|
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var i = 0
|
var i = 0
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume((i++).toString())
|
x.resume((i++).toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
// WITH_REFLECT
|
// WITH_REFLECT
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun runInstanceOf(x: Continuation<Boolean>) {
|
suspend fun runInstanceOf(): Boolean = suspendWithCurrentContinuation { x ->
|
||||||
val y: Any = x
|
val y: Any = x
|
||||||
x.resume(x is Continuation<*>)
|
x.resume(x is Continuation<*>)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun runCast(x: Continuation<Boolean>) {
|
suspend fun runCast(): Boolean = suspendWithCurrentContinuation { x ->
|
||||||
val y: Any = x
|
val y: Any = x
|
||||||
x.resume(Continuation::class.isInstance(y as Continuation<*>))
|
x.resume(Continuation::class.isInstance(y as Continuation<*>))
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun <V> suspendHere(v: V, x: Continuation<V>) {
|
suspend fun <V> suspendHere(v: V): V = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(v: String, x: Continuation<String>) {
|
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var result = ""
|
var result = ""
|
||||||
var ok = false
|
var ok = false
|
||||||
suspend fun suspendHere(v: String, x: Continuation<Unit>) {
|
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
|
||||||
result += v
|
result += v
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var wasHandleResultCalled = false
|
var wasHandleResultCalled = false
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var wasHandleResultCalled = false
|
var wasHandleResultCalled = false
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var ok = false
|
var ok = false
|
||||||
var v = "fail"
|
var v = "fail"
|
||||||
suspend fun suspendHere(v: String, x: Continuation<Unit>) {
|
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
|
||||||
this.v = v
|
this.v = v
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,11 +14,11 @@ fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
|||||||
fun box(): String {
|
fun box(): String {
|
||||||
var result = "fail"
|
var result = "fail"
|
||||||
|
|
||||||
val lambda: Controller.() -> Continuation<Unit> = {
|
val lambda: Controller.() -> Continuation<Unit> = l1@{
|
||||||
object : Continuation<Any?> {
|
object : Continuation<Any?> {
|
||||||
override fun resume(data: Any?) {
|
override fun resume(data: Any?) {
|
||||||
if (data == Unit) {
|
if (data == Unit) {
|
||||||
suspendHere(this)
|
this@l1.javaClass.getMethod("suspendHere", Continuation::class.java).invoke(this@l1, this)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
package lib
|
package lib
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,36 +4,26 @@ package lib
|
|||||||
|
|
||||||
@AllowSuspendExtensions
|
@AllowSuspendExtensions
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun String.suspendHere(x: Continuation<String>) {
|
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(this)
|
x.resume(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline suspend fun String.inlineSuspendHere(x: Continuation<String>) {
|
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
|
||||||
suspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun Controller.suspendExtension(v: String, x: Continuation<String>) {
|
suspend fun Controller.suspendExtension(v: String): String = v.suspendHere()
|
||||||
v.suspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline suspend fun Controller.inlineSuspendExtension(v: String, x: Continuation<String>) {
|
inline suspend fun Controller.inlineSuspendExtension(v: String) = v.inlineSuspendHere()
|
||||||
v.inlineSuspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: main(controller)
|
// MODULE: main(controller)
|
||||||
// FILE: main.kt
|
// FILE: main.kt
|
||||||
import lib.*
|
import lib.*
|
||||||
|
|
||||||
suspend fun Controller.localSuspendExtension(v: String, x: Continuation<String>) {
|
suspend fun Controller.localSuspendExtension(v: String) = v.suspendHere()
|
||||||
v.suspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline suspend fun Controller.localInlineSuspendExtension(v: String, x: Continuation<String>) {
|
inline suspend fun Controller.localInlineSuspendExtension(v: String) = v.inlineSuspendHere()
|
||||||
v.inlineSuspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||||
c(Controller()).resume(Unit)
|
c(Controller()).resume(Unit)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var lastSuspension: Continuation<String>? = null
|
var lastSuspension: Continuation<String>? = null
|
||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
|
Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
+2
-1
@@ -1,8 +1,9 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var lastSuspension: Continuation<String>? = null
|
var lastSuspension: Continuation<String>? = null
|
||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
|
Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
+2
-1
@@ -1,8 +1,9 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var lastSuspension: Continuation<String>? = null
|
var lastSuspension: Continuation<String>? = null
|
||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
|
Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
+2
-1
@@ -1,8 +1,9 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var lastSuspension: Continuation<String>? = null
|
var lastSuspension: Continuation<String>? = null
|
||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
|
Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ var wasCalled = false
|
|||||||
class Controller {
|
class Controller {
|
||||||
val postponedActions = ArrayList<() -> Unit>()
|
val postponedActions = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var cResult = 0
|
var cResult = 0
|
||||||
suspend fun suspendHere(v: Int, x: Continuation<Int>) {
|
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v * 2)
|
x.resume(v * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
var cResult = 0
|
var cResult = 0
|
||||||
suspend fun suspendHere(v: Int, x: Continuation<Int>) {
|
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v * 2)
|
x.resume(v * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var res = 0
|
var res = 0
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resumeWithException(RuntimeException("OK"))
|
x.resumeWithException(RuntimeException("OK"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var res = 0
|
var res = 0
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var globalResult = ""
|
var globalResult = ""
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendThere()
|
||||||
suspendThere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun suspendThere(x: Continuation<String>) {
|
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,17 @@
|
|||||||
@AllowSuspendExtensions
|
@AllowSuspendExtensions
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun String.suspendHere(x: Continuation<String>) {
|
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(this)
|
x.resume(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline suspend fun String.inlineSuspendHere(x: Continuation<String>) {
|
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
|
||||||
suspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun Controller.suspendExtension(v: String, x: Continuation<String>) {
|
suspend fun Controller.suspendExtension(v: String): String = v.suspendHere()
|
||||||
v.suspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline suspend fun Controller.inlineSuspendExtension(v: String, x: Continuation<String>) {
|
inline suspend fun Controller.inlineSuspendExtension(v: String): String = v.inlineSuspendHere()
|
||||||
v.inlineSuspendHere(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||||
c(Controller()).resume(Unit)
|
c(Controller()).resume(Unit)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(v: Int, x: Continuation<Int>) {
|
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v * 2)
|
x.resume(v * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
var i = 0
|
var i = 0
|
||||||
suspend fun suspendHere(x: Continuation<Int>) {
|
suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(i++)
|
x.resume(i++)
|
||||||
}
|
}
|
||||||
suspend fun suspendThere(x: Continuation<String>) {
|
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("?")
|
x.resume("?")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,13 +1,13 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("K")
|
x.resume("K")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithArgument(v: String, x: Continuation<String>) {
|
suspend fun suspendWithArgument(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithDouble(v: Double, x: Continuation<Double>) {
|
suspend fun suspendWithDouble(v: Double): Double = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -4,13 +4,13 @@ var wasCalled = false
|
|||||||
class Controller {
|
class Controller {
|
||||||
val postponedActions = ArrayList<() -> Unit>()
|
val postponedActions = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ var wasCalled = false
|
|||||||
class Controller {
|
class Controller {
|
||||||
val postponedActions = ArrayList<() -> Unit>()
|
val postponedActions = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(v: String, x: Continuation<String>) {
|
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ var wasCalled = false
|
|||||||
class Controller {
|
class Controller {
|
||||||
val postponedActions = mutableListOf<() -> Unit>()
|
val postponedActions = mutableListOf<() -> Unit>()
|
||||||
|
|
||||||
suspend fun suspendWithValue(v: String, x: Continuation<String>) {
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception, x: Continuation<String>) {
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ inline fun inline() {}
|
|||||||
class External { external fun external() }
|
class External { external fun external() }
|
||||||
operator fun Unit.invoke() {}
|
operator fun Unit.invoke() {}
|
||||||
infix fun Unit.infix(unit: Unit) {}
|
infix fun Unit.infix(unit: Unit) {}
|
||||||
class Suspend { suspend fun suspend(c: Continuation<Unit>) {} }
|
// TODO: support or prohibit references to suspend functions
|
||||||
|
// class Suspend { suspend fun suspend(c: Continuation<Unit>) {} }
|
||||||
|
|
||||||
val externalGetter = Unit
|
val externalGetter = Unit
|
||||||
external get
|
external get
|
||||||
@@ -44,11 +45,11 @@ fun box(): String {
|
|||||||
assertTrue(Unit::infix.isInfix)
|
assertTrue(Unit::infix.isInfix)
|
||||||
assertFalse(Unit::infix.isSuspend)
|
assertFalse(Unit::infix.isSuspend)
|
||||||
|
|
||||||
assertFalse(Suspend::suspend.isInline)
|
// assertFalse(Suspend::suspend.isInline)
|
||||||
assertFalse(Suspend::suspend.isExternal)
|
// assertFalse(Suspend::suspend.isExternal)
|
||||||
assertFalse(Suspend::suspend.isOperator)
|
// assertFalse(Suspend::suspend.isOperator)
|
||||||
assertFalse(Suspend::suspend.isInfix)
|
// assertFalse(Suspend::suspend.isInfix)
|
||||||
assertTrue(Suspend::suspend.isSuspend)
|
// assertTrue(Suspend::suspend.isSuspend)
|
||||||
|
|
||||||
assertTrue(::externalGetter.getter.isExternal)
|
assertTrue(::externalGetter.getter.isExternal)
|
||||||
assertFalse(::externalGetter.getter.isInline)
|
assertFalse(::externalGetter.getter.isInline)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere() = suspendWithCurrentContinuation<String> { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere() = ""
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<Unit>) {
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ class FutureController<T> {
|
|||||||
val future = CompletableFuture<T>()
|
val future = CompletableFuture<T>()
|
||||||
|
|
||||||
|
|
||||||
suspend fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>) {
|
suspend fun <V> await(f: CompletableFuture<V>) = suspendWithCurrentContinuation<V> { machine ->
|
||||||
f.whenComplete { value, throwable ->
|
f.whenComplete { value, throwable ->
|
||||||
if (throwable == null)
|
if (throwable == null)
|
||||||
machine.resume(value)
|
machine.resume(value)
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ fun <T> async(coroutine c: FutureController<T>.() -> Continuation<Unit>): Comple
|
|||||||
class FutureController<T> {
|
class FutureController<T> {
|
||||||
val future = CompletableFuture<T>()
|
val future = CompletableFuture<T>()
|
||||||
|
|
||||||
suspend fun <V> await(f: CompletableFuture<V>, machine: Continuation<V>) {
|
suspend fun <V> await(f: CompletableFuture<V>) = suspendWithCurrentContinuation<V> { machine ->
|
||||||
f.whenComplete { value, throwable ->
|
f.whenComplete { value, throwable ->
|
||||||
if (throwable == null)
|
if (throwable == null)
|
||||||
machine.resume(value)
|
machine.resume(value)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// FILE: A.kt
|
// FILE: A.kt
|
||||||
package a
|
package a
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(x: Continuation<String>) {
|
suspend fun suspendHere() = suspendWithCurrentContinuation<String> { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ fun async(coroutine x: Controller.() -> Continuation<Unit>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
suspend fun step(param: Int, next: Continuation<Int>) {
|
suspend fun step(param: Int) = suspendWithCurrentContinuation<Int> { next ->
|
||||||
next.resume(param + 1)
|
next.resume(param + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user