diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 664b61b918b..aada5c22e97 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -78,6 +78,7 @@ import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; 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.inline.InlineUtil; import org.jetbrains.kotlin.resolve.jvm.AsmTypes; @@ -1900,15 +1901,29 @@ public class ExpressionCodegen extends KtVisitor impleme @NotNull public StackValue genCoroutineInstanceValueFromResolvedCall(@NotNull ResolvedCall resolvedCall) { - ExtensionReceiver controllerReceiver = getControllerReceiverFromResolvedCall(resolvedCall); - ClassDescriptor coroutineClassDescriptor = - bindingContext.get(CodegenBinding.CLASS_FOR_CALLABLE, controllerReceiver.getDeclarationDescriptor()); - assert coroutineClassDescriptor != null : "Coroutine class descriptor should not be null"; + return getCoroutineInstanceValueByReceiver(getControllerReceiverFromResolvedCall(resolvedCall)); + } - // second argument for handleResult is always Continuation ('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); } + @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) { ReceiverValue controllerReceiver = resolvedCall.getDispatchReceiver() != null @@ -2515,7 +2530,14 @@ public class ExpressionCodegen extends KtVisitor impleme } 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 @@ -2754,9 +2776,17 @@ public class ExpressionCodegen extends KtVisitor impleme @NotNull public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall resolvedCall, @NotNull StackValue receiver) { ResolvedCallWithRealDescriptor callWithRealDescriptor = - CoroutineCodegenUtilKt.replaceSuspensionFunctionViewWithRealDescriptor(resolvedCall, state.getProject()); + CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor( + resolvedCall, state.getProject(), state.getBindingContext() + ); 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); } FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall); @@ -2778,7 +2808,7 @@ public class ExpressionCodegen extends KtVisitor impleme 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 return new OperationStackValue(getSuspensionReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda()); } @@ -2786,6 +2816,25 @@ public class ExpressionCodegen extends KtVisitor impleme 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 // 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) { @@ -2838,7 +2887,7 @@ public class ExpressionCodegen extends KtVisitor impleme @NotNull CallGenerator callGenerator, @NotNull ArgumentGenerator argumentGenerator ) { - boolean isSuspensionPoint = CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall); + boolean isSuspensionPoint = CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext); if (isSuspensionPoint) { // Inline markers are used to spill the stack before coroutine suspension addInlineMarker(v, true); @@ -2876,11 +2925,11 @@ public class ExpressionCodegen extends KtVisitor impleme } if (isSuspensionPoint) { - v.aconst(getSuspensionReturnTypeByResolvedCall(resolvedCall).getDescriptor()); + v.tconst(getSuspensionReturnTypeByResolvedCall(resolvedCall)); v.invokestatic( CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER, CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME, - "(Ljava/lang/String;)V", false); + "(Ljava/lang/Class;)V", false); } callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this); @@ -2905,8 +2954,13 @@ public class ExpressionCodegen extends KtVisitor impleme assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor : "Suspension point resolved call should be built on SimpleFunctionDescriptor"; - KotlinType returnType = org.jetbrains.kotlin.resolve.coroutine.CoroutineUtilKt - .getSuspensionPointReturnType((SimpleFunctionDescriptor) resolvedCall.getResultingDescriptor()); + FunctionDescriptor initialSignature = + ((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"; return typeMapper.mapType(returnType); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 6b23f3fc40f..51d9cf1ab0a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -21,8 +21,8 @@ import com.intellij.psi.PsiElement; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import kotlin.collections.CollectionsKt; import kotlin.Unit; +import kotlin.collections.CollectionsKt; import kotlin.jvm.functions.Function1; import kotlin.text.StringsKt; 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.ImplKt; 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.state.GenerationState; 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.codegen.AsmUtil.*; -import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isAnnotationOrJvm6Interface; -import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8Interface; -import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceMember; +import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*; 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.annotations.AnnotationUseSiteTarget.*; @@ -128,6 +127,10 @@ public class FunctionCodegen { 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()) { generateMethod(JvmDeclarationOriginKt.OtherOrigin(function, functionDescriptor), functionDescriptor, new FunctionGenerationStrategy.FunctionDefault(state, function)); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt index 398b7014532..005330d2700 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmRuntimeTypes.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.codegen +import org.jetbrains.kotlin.codegen.coroutines.continuationClassDescriptor import org.jetbrains.kotlin.codegen.coroutines.hasNoinlineInterceptResume import org.jetbrains.kotlin.coroutines.controllerTypeIfCoroutine 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.name.FqName 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.descriptorUtil.builtIns import org.jetbrains.kotlin.types.KotlinType @@ -59,7 +59,7 @@ class JvmRuntimeTypes(module: ModuleDescriptor) { * @return `Continuation` type */ private fun createNullableAnyContinuation(module: ModuleDescriptor): KotlinType { - val classDescriptor = module.builtIns.getBuiltInClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME) + val classDescriptor = module.builtIns.continuationClassDescriptor return TypeConstructorSubstitution.createByParametersMap( mapOf(classDescriptor.declaredTypeParameters.single() to TypeProjectionImpl(module.builtIns.nullableAnyType)) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index 5d93e68143d..9c5036abb83 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -20,6 +20,8 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.containers.Stack; +import kotlin.Pair; +import kotlin.collections.CollectionsKt; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -432,6 +434,33 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { // working around a problem with shallow analysis 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 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); if (nameForClassOrPackageMember != null) { nameStack.push(nameForClassOrPackageMember); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index ad2cb439779..92023cefec5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -71,6 +71,12 @@ public class CodegenBinding { public static final WritableSlice CUSTOM_STRATEGY_FOR_INLINE_LAMBDA = Slices.createSimpleSlice(); public static final WritableSlice CUSTOM_DESCRIPTOR_FOR_INLINE_LAMBDA = Slices.createSimpleSlice(); + public static final WritableSlice SUSPEND_FUNCTION_TO_JVM_VIEW = + Slices.createSimpleSlice(); + + public static final WritableSlice PARAMETER_SYNONYM = + Slices.createSimpleSlice(); + static { BasicWritableSlice.initSliceDebugNames(CodegenBinding.class); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/MethodContext.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/MethodContext.java index 545e6948afb..2c2a152b7b5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/context/MethodContext.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/context/MethodContext.java @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.JvmCodegenUtil; import org.jetbrains.kotlin.codegen.OwnerKind; import org.jetbrains.kotlin.codegen.StackValue; 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.KotlinTypeMapper; import org.jetbrains.kotlin.descriptors.*; @@ -79,7 +80,10 @@ public class MethodContext extends CodegenContext { @Nullable 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()); } ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt index d559cf9e1ae..1b29c6b7eb1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt @@ -171,7 +171,7 @@ class CoroutineTransformerMethodVisitor( suspensionCallBegin = beforeSuspensionPointMarker, suspensionCallEnd = methodInsn, fakeReturnValueInsns = fakeReturnValueInsns, - returnType = Type.getType((beforeSuspensionPointMarker.previous as LdcInsnNode).cst as String)) + returnType = (beforeSuspensionPointMarker.previous as LdcInsnNode).cst as Type) suspensionPoints.add(suspensionPoint) // Drop type info from marker diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt index 2c0ef1564cf..6a7ebd96bbe 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/coroutineCodegenUtil.kt @@ -17,13 +17,19 @@ package org.jetbrains.kotlin.codegen.coroutines 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.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.name.Name import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingTraceContext -import org.jetbrains.kotlin.resolve.DelegatingBindingTrace +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments 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.TracingStrategy import org.jetbrains.kotlin.resolve.calls.util.CallMaker -import org.jetbrains.kotlin.resolve.coroutine.REPLACED_SUSPENSION_POINT_KEY -import org.jetbrains.kotlin.resolve.coroutine.SUSPENSION_POINT_KEY +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.TypeConstructorSubstitution import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.typeUtil.asTypeProjection 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 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_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 {} // Resolved calls to suspension function contain descriptors as they visible within coroutines: // E.g. `fun await(f: CompletableFuture): V` instead of `fun await(f: CompletableFuture, machine: Continuation): 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. // So this function returns resolved call with descriptor looking like `fun await(f: CompletableFuture, machine: Continuation): Unit` // and fake `this` expression that used as argument for second parameter -fun ResolvedCall<*>.replaceSuspensionFunctionViewWithRealDescriptor( - project: Project +fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor( + project: Project, + bindingContext: BindingContext ): ResolvedCallWithRealDescriptor? { - val function = candidateDescriptor as? FunctionDescriptor ?: return null - if (!isSuspensionPoint()) return null - - val initialSignatureDescriptor = function.initialSignatureDescriptor ?: return null - if (function.getUserData(REPLACED_SUSPENSION_POINT_KEY) == true) return null + val function = candidateDescriptor as? SimpleFunctionDescriptor ?: return null + if (!function.isSuspend || function.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) != null) return null val newCandidateDescriptor = - initialSignatureDescriptor.createCustomCopy { - setPreserveSourceElement() - setSignatureChange() - putUserData(SUSPENSION_POINT_KEY, true) - putUserData(REPLACED_SUSPENSION_POINT_KEY, true) - } + bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, function) + ?: createJvmSuspendFunctionView(function) val newCall = ResolvedCallImpl( call, @@ -180,13 +185,35 @@ fun createResolvedCallForInterceptResume( return InterceptResumeCallContext(resolvedCall, thisExpression) } -fun ResolvedCall<*>.isSuspensionPoint() = - (candidateDescriptor as? FunctionDescriptor)?.let { it.isSuspend && it.getUserData(SUSPENSION_POINT_KEY) ?: false } - ?: false +fun ResolvedCall<*>.isSuspensionPoint(bindingContext: BindingContext) = + bindingContext[BindingContext.COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, call] != null -private fun FunctionDescriptor.createCustomCopy( - copySettings: FunctionDescriptor.CopyBuilder.(FunctionDescriptor) -> FunctionDescriptor.CopyBuilder -): FunctionDescriptor { +// Suspend functions have irregular signatures on JVM, containing an additional last parameter with type `Continuation`, +// and return type Unit (later it will be replaced with 'Any?') +// This function returns a function descriptor reflecting how the suspend function looks from point of view of JVM +fun 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.(FunctionDescriptor) + -> FunctionDescriptor.CopyBuilder + +private fun D.createCustomCopy( + copySettings: FunctionDescriptorCopyBuilderToFunctionDescriptorCopyBuilder +): D { val newOriginal = if (original !== this) @@ -198,9 +225,18 @@ private fun FunctionDescriptor.createCustomCopy( 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() = findOperatorInController(this, OperatorNameConventions.COROUTINE_INTERCEPT_RESUME)?.isInline == true @@ -209,3 +245,55 @@ fun KotlinType.hasNoinlineInterceptResume() = fun findOperatorInController(controllerType: KotlinType, name: Name): SimpleFunctionDescriptor? = 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 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 56db9cf7101..96be20e292b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment; import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; 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.state.GenerationState; 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)); } + 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 Method asmMethod = diff --git a/compiler/testData/codegen/box/coroutines/beginWithException.kt b/compiler/testData/codegen/box/coroutines/beginWithException.kt index 45bc615447d..fc08a1b18af 100644 --- a/compiler/testData/codegen/box/coroutines/beginWithException.kt +++ b/compiler/testData/codegen/box/coroutines/beginWithException.kt @@ -6,7 +6,7 @@ class Controller { exception = t } - suspend fun suspendHere(x: Continuation) {} + suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->} // INTERCEPT_RESUME_PLACEHOLDER } diff --git a/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt b/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt index b7abcc41fdf..101ac232df2 100644 --- a/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt +++ b/compiler/testData/codegen/box/coroutines/beginWithExceptionNoHandleException.kt @@ -1,6 +1,6 @@ // WITH_RUNTIME class Controller { - suspend fun suspendHere(x: Continuation) {} + suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->} // INTERCEPT_RESUME_PLACEHOLDER } diff --git a/compiler/testData/codegen/box/coroutines/coercionToUnit.kt b/compiler/testData/codegen/box/coroutines/coercionToUnit.kt index 264363c23fd..e8d59dd7b7b 100644 --- a/compiler/testData/codegen/box/coroutines/coercionToUnit.kt +++ b/compiler/testData/codegen/box/coroutines/coercionToUnit.kt @@ -4,7 +4,7 @@ class Controller { result = "OK" } - suspend fun await(t: T, c: Continuation) { + suspend fun await(t: T): T = suspendWithCurrentContinuation { c -> c.resume(t) } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt b/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt index 4fac18968b0..ba7b8899639 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/breakFinally.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt index b5141c96108..856364d087d 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/breakStatement.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt index af76f56fc91..59f162579ce 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt b/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt index eed3dcea86c..8e4ace21114 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/forContinue.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt index 67d5f34b2b3..f4e95f2935c 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/forStatement.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt index 649eeb3669e..cdef39823b4 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/ifStatement.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt b/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt index 13c96817486..1de29d0952a 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/returnFromFinally.kt @@ -8,7 +8,7 @@ class Controller { var result = "" - suspend fun suspendAndLog(value: T, c: Continuation) { + suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { c -> result += "suspend($value);" c.resume(value) } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt b/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt index ef4268e0689..9509dce93d4 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> result += "[" c.resume(value) } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt b/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt index 919c2cb7d91..d4a1cf008f1 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt @@ -4,12 +4,12 @@ class Controller { var result = "" - suspend fun suspendAndLog(value: T, c: Continuation) { + suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { c -> result += "suspend($value);" c.resume(value) } - suspend fun suspendLogAndThrow(exception: Throwable, c: Continuation) { + suspend fun suspendLogAndThrow(exception: Throwable): Nothing = suspendWithCurrentContinuation { c -> result += "throw(${exception.message});" c.resumeWithException(exception) } diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt index 1fd07ba0095..8d8c15051bd 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/throwInTryWithHandleResult.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendAndLog(value: T, c: Continuation) { + suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { c -> result += "suspend($value);" c.resume(value) } @@ -35,4 +35,4 @@ fun box(): String { } return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt b/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt index 2daa0827e00..f0d31b7f601 100644 --- a/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt +++ b/compiler/testData/codegen/box/coroutines/controlFlow/whileStatement.kt @@ -4,7 +4,7 @@ class Controller { var result = "" - suspend fun suspendWithResult(value: T, c: Continuation) { + suspend fun suspendWithResult(value: T): T = suspendWithCurrentContinuation { c -> c.resume(value) } } diff --git a/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt b/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt index 8ecb16c3c90..b32b36fcc65 100644 --- a/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt +++ b/compiler/testData/codegen/box/coroutines/controllerAccessFromInnerLambda.kt @@ -1,6 +1,6 @@ class Controller { var result = false - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt b/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt index f2a5d6937f6..f0451f380ce 100644 --- a/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt +++ b/compiler/testData/codegen/box/coroutines/defaultParametersInSuspend.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(a: String = "abc", i: Int = 2, x: Continuation) { + suspend fun suspendHere(a: String = "abc", i: Int = 2): String = suspendWithCurrentContinuation { x -> x.resume(a + "#" + (i + 1)) } diff --git a/compiler/testData/codegen/box/coroutines/emptyClosure.kt b/compiler/testData/codegen/box/coroutines/emptyClosure.kt index 36fa1f59a67..57aa2c0f819 100644 --- a/compiler/testData/codegen/box/coroutines/emptyClosure.kt +++ b/compiler/testData/codegen/box/coroutines/emptyClosure.kt @@ -1,7 +1,7 @@ var result = 0 class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> result++ x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt b/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt index 8a07ae8dc08..91f4d8001f2 100644 --- a/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt +++ b/compiler/testData/codegen/box/coroutines/falseUnitCoercion.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(v: T, x: Continuation) { + suspend fun suspendHere(v: T): T = suspendWithCurrentContinuation { x -> x.resume(v) } diff --git a/compiler/testData/codegen/box/coroutines/generate.kt b/compiler/testData/codegen/box/coroutines/generate.kt index 2d7522606c6..4cbf793725f 100644 --- a/compiler/testData/codegen/box/coroutines/generate.kt +++ b/compiler/testData/codegen/box/coroutines/generate.kt @@ -43,7 +43,7 @@ class GeneratorController() : AbstractIterator() { this.nextStep = step } - suspend fun yield(value: T, c: Continuation) { + suspend fun yield(value: T): Unit = suspendWithCurrentContinuation { c -> setNext(value) setNextStep(c) } diff --git a/compiler/testData/codegen/box/coroutines/handleException.kt b/compiler/testData/codegen/box/coroutines/handleException.kt index b9690cc1c2e..0783e750377 100644 --- a/compiler/testData/codegen/box/coroutines/handleException.kt +++ b/compiler/testData/codegen/box/coroutines/handleException.kt @@ -3,13 +3,13 @@ class Controller { var exception: Throwable? = null val postponedActions = ArrayList<() -> Unit>() - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resume(v) } } - suspend fun suspendWithException(e: Exception, x: Continuation) { + suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } diff --git a/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt b/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt index 547c24f9cc4..d7bdf7cd5e0 100644 --- a/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt +++ b/compiler/testData/codegen/box/coroutines/handleResultNonUnitExpression.kt @@ -1,6 +1,6 @@ class Controller { var isCompleted = false - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt b/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt index bdcbea1bc02..88a360a47dc 100644 --- a/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt +++ b/compiler/testData/codegen/box/coroutines/handleResultSuspended.kt @@ -1,7 +1,7 @@ class Controller { var log = "" - suspend fun suspendAndLog(value: T, x: Continuation) { + suspend fun suspendAndLog(value: T): T = suspendWithCurrentContinuation { x -> log += "suspend($value);" x.resume(value) } diff --git a/compiler/testData/codegen/box/coroutines/illegalState.kt b/compiler/testData/codegen/box/coroutines/illegalState.kt index 0f9eda9538b..690e588cc1a 100644 --- a/compiler/testData/codegen/box/coroutines/illegalState.kt +++ b/compiler/testData/codegen/box/coroutines/illegalState.kt @@ -2,7 +2,7 @@ // TARGET_BACKEND: JVM // NO_INTERCEPT_RESUME_TESTS class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt b/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt index 3c7ebaef057..1a3b884b3ef 100644 --- a/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt +++ b/compiler/testData/codegen/box/coroutines/inlineSuspendFunction.kt @@ -8,17 +8,13 @@ class Controller { x.resume(v) } - suspend inline fun suspendInline(v: String, x: Continuation) { + suspend inline fun suspendInline(v: String): String = suspendWithCurrentContinuation { x -> withValue(v, x) } - suspend inline fun suspendInline(crossinline b: () -> String, x: Continuation) { - suspendInline(b(), x) - } + suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b()) - suspend inline fun suspendInline(x: Continuation) { - suspendInline({ T::class.simpleName!! }, x) - } + suspend inline fun suspendInline(): String = suspendInline({ T::class.simpleName!! }) // INTERCEPT_RESUME_PLACEHOLDER } diff --git a/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt b/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt index c25321154d8..dc197a537cf 100644 --- a/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt +++ b/compiler/testData/codegen/box/coroutines/inlinedTryCatchFinally.kt @@ -4,13 +4,13 @@ var wasCalled = false class Controller { val postponedActions = mutableListOf<() -> Unit>() - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resume(v) } } - suspend fun suspendWithException(e: Exception, x: Continuation) { + suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } diff --git a/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt b/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt index a3e8d6aaeb5..91c52a38cff 100644 --- a/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt +++ b/compiler/testData/codegen/box/coroutines/innerSuspensionCalls.kt @@ -1,6 +1,6 @@ class Controller { var i = 0 - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume((i++).toString()) } diff --git a/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt b/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt index f2c8450e69a..c06aca1304f 100644 --- a/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt +++ b/compiler/testData/codegen/box/coroutines/instanceOfContinuation.kt @@ -2,12 +2,12 @@ // WITH_REFLECT class Controller { - suspend fun runInstanceOf(x: Continuation) { + suspend fun runInstanceOf(): Boolean = suspendWithCurrentContinuation { x -> val y: Any = x x.resume(x is Continuation<*>) } - suspend fun runCast(x: Continuation) { + suspend fun runCast(): Boolean = suspendWithCurrentContinuation { x -> val y: Any = x x.resume(Continuation::class.isInstance(y as Continuation<*>)) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt index 3949bfb83ab..d8ad949feae 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/complicatedMerge.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt index 242d26ce688..1ada17280c8 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt index b223e711dd4..2051ae588c9 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt index 67a26a5baab..83b6d0d15fd 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromByteArray.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt index 90dabd283c7..b8d8df5a346 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/noVariableInTable.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt index 6aacb10e705..cc290b87e3a 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt index 6a58a59cfba..b9f15afbc8c 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInArrayStore.kt @@ -1,7 +1,7 @@ // WITH_RUNTIME // TARGET_BACKEND: JVM class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt index b8a863ea44a..d46ba81d141 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInMethodCall.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt index 47ed21240cd..ca0ab1bab23 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInPutfield.kt @@ -1,7 +1,7 @@ // WITH_RUNTIME // TARGET_BACKEND: JVM class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt index b58dfb8ee7c..a797784b92e 100644 --- a/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt +++ b/compiler/testData/codegen/box/coroutines/intLikeVarSpilling/usedInVarStore.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/iterateOverArray.kt b/compiler/testData/codegen/box/coroutines/iterateOverArray.kt index 4849fa72044..6b4575b2918 100644 --- a/compiler/testData/codegen/box/coroutines/iterateOverArray.kt +++ b/compiler/testData/codegen/box/coroutines/iterateOverArray.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/kt12958.kt b/compiler/testData/codegen/box/coroutines/kt12958.kt index 41e4631c20b..e97b978abfb 100644 --- a/compiler/testData/codegen/box/coroutines/kt12958.kt +++ b/compiler/testData/codegen/box/coroutines/kt12958.kt @@ -1,6 +1,6 @@ class Controller { var result = "fail" - suspend fun suspendHere(v: V, x: Continuation) { + suspend fun suspendHere(v: V): V = suspendWithCurrentContinuation { x -> x.resume(v) } diff --git a/compiler/testData/codegen/box/coroutines/lambdaParameters.kt b/compiler/testData/codegen/box/coroutines/lambdaParameters.kt index c6628e5715e..fad8981eed8 100644 --- a/compiler/testData/codegen/box/coroutines/lambdaParameters.kt +++ b/compiler/testData/codegen/box/coroutines/lambdaParameters.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(v: String, x: Continuation) { + suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) } diff --git a/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt b/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt index e61564905e5..bf5cd7a1790 100644 --- a/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt +++ b/compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt @@ -1,7 +1,7 @@ class Controller { var result = "" var ok = false - suspend fun suspendHere(v: String, x: Continuation) { + suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x -> result += v x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt index 2135e0686e7..53ea9eb52a3 100644 --- a/compiler/testData/codegen/box/coroutines/lastStatementInc.kt +++ b/compiler/testData/codegen/box/coroutines/lastStatementInc.kt @@ -1,6 +1,6 @@ class Controller { var wasHandleResultCalled = false - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt index 7dc36448c04..822560e7f7d 100644 --- a/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt +++ b/compiler/testData/codegen/box/coroutines/lastStementAssignment.kt @@ -1,6 +1,6 @@ class Controller { var wasHandleResultCalled = false - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt b/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt index d4b6cdcbae0..586ed9261e6 100644 --- a/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt +++ b/compiler/testData/codegen/box/coroutines/lastUnitExpression.kt @@ -1,7 +1,7 @@ class Controller { var ok = false var v = "fail" - suspend fun suspendHere(v: String, x: Continuation) { + suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x -> this.v = v x.resume(Unit) } diff --git a/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt b/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt index b424649cac6..3bfdfb6e063 100644 --- a/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt +++ b/compiler/testData/codegen/box/coroutines/manualContinuationImpl.kt @@ -1,5 +1,6 @@ +// WITH_RUNTIME class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } @@ -13,11 +14,11 @@ fun builder(coroutine c: Controller.() -> Continuation) { fun box(): String { var result = "fail" - val lambda: Controller.() -> Continuation = { + val lambda: Controller.() -> Continuation = l1@{ object : Continuation { override fun resume(data: Any?) { if (data == Unit) { - suspendHere(this) + this@l1.javaClass.getMethod("suspendHere", Continuation::class.java).invoke(this@l1, this) return } diff --git a/compiler/testData/codegen/box/coroutines/multiModule/simple.kt b/compiler/testData/codegen/box/coroutines/multiModule/simple.kt index ee35053ca86..a722c5d8cef 100644 --- a/compiler/testData/codegen/box/coroutines/multiModule/simple.kt +++ b/compiler/testData/codegen/box/coroutines/multiModule/simple.kt @@ -3,7 +3,7 @@ package lib class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt b/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt index 1fcaa7bb796..37fcedb04db 100644 --- a/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt +++ b/compiler/testData/codegen/box/coroutines/multiModule/suspendExtension.kt @@ -4,36 +4,26 @@ package lib @AllowSuspendExtensions class Controller { - suspend fun String.suspendHere(x: Continuation) { + suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume(this) } - inline suspend fun String.inlineSuspendHere(x: Continuation) { - suspendHere(x) - } + inline suspend fun String.inlineSuspendHere(): String = suspendHere() // INTERCEPT_RESUME_PLACEHOLDER } -suspend fun Controller.suspendExtension(v: String, x: Continuation) { - v.suspendHere(x) -} +suspend fun Controller.suspendExtension(v: String): String = v.suspendHere() -inline suspend fun Controller.inlineSuspendExtension(v: String, x: Continuation) { - v.inlineSuspendHere(x) -} +inline suspend fun Controller.inlineSuspendExtension(v: String) = v.inlineSuspendHere() // MODULE: main(controller) // FILE: main.kt import lib.* -suspend fun Controller.localSuspendExtension(v: String, x: Continuation) { - v.suspendHere(x) -} +suspend fun Controller.localSuspendExtension(v: String) = v.suspendHere() -inline suspend fun Controller.localInlineSuspendExtension(v: String, x: Continuation) { - v.inlineSuspendHere(x) -} +inline suspend fun Controller.localInlineSuspendExtension(v: String) = v.inlineSuspendHere() fun builder(coroutine c: Controller.() -> Continuation) { c(Controller()).resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt index 8e49083773e..b21f67a46c4 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCalls.kt @@ -1,8 +1,9 @@ class Controller { var lastSuspension: Continuation? = null var result = "fail" - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x + Unit } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt index c793ce03b05..13c14853942 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda1.kt @@ -1,8 +1,9 @@ class Controller { var lastSuspension: Continuation? = null var result = "fail" - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x + Unit } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt index 4df1a8a1532..8b10f44ba3b 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda2.kt @@ -1,8 +1,9 @@ class Controller { var lastSuspension: Continuation? = null var result = "fail" - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x + Unit } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt index f7f728e0639..9b835cdad78 100644 --- a/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt +++ b/compiler/testData/codegen/box/coroutines/multipleInvokeCallsInsideInlineLambda3.kt @@ -1,8 +1,9 @@ class Controller { var lastSuspension: Continuation? = null var result = "fail" - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> lastSuspension = x + Unit } fun hasNext() = lastSuspension != null diff --git a/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt b/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt index 3671921ae3f..8f6be4248e1 100644 --- a/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt +++ b/compiler/testData/codegen/box/coroutines/nestedTryCatch.kt @@ -4,13 +4,13 @@ var wasCalled = false class Controller { val postponedActions = ArrayList<() -> Unit>() - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resume(v) } } - suspend fun suspendWithException(e: Exception, x: Continuation) { + suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } diff --git a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt index 5239de89163..64e06002352 100644 --- a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambda.kt @@ -1,6 +1,6 @@ class Controller { var cResult = 0 - suspend fun suspendHere(v: Int, x: Continuation) { + suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x -> x.resume(v * 2) } diff --git a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt index 56a49681320..33f8a86d325 100644 --- a/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt +++ b/compiler/testData/codegen/box/coroutines/nonLocalReturnFromInlineLambdaDeep.kt @@ -2,7 +2,7 @@ class Controller { var cResult = 0 - suspend fun suspendHere(v: Int, x: Continuation) { + suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x -> x.resume(v * 2) } diff --git a/compiler/testData/codegen/box/coroutines/returnByLabel.kt b/compiler/testData/codegen/box/coroutines/returnByLabel.kt index d41ada18134..4da5049cd54 100644 --- a/compiler/testData/codegen/box/coroutines/returnByLabel.kt +++ b/compiler/testData/codegen/box/coroutines/returnByLabel.kt @@ -1,6 +1,6 @@ class Controller { var res = 0 - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/simple.kt b/compiler/testData/codegen/box/coroutines/simple.kt index 3fb38062032..accacc25412 100644 --- a/compiler/testData/codegen/box/coroutines/simple.kt +++ b/compiler/testData/codegen/box/coroutines/simple.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/simpleException.kt b/compiler/testData/codegen/box/coroutines/simpleException.kt index 36f31cfa127..d1f98c29d1c 100644 --- a/compiler/testData/codegen/box/coroutines/simpleException.kt +++ b/compiler/testData/codegen/box/coroutines/simpleException.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resumeWithException(RuntimeException("OK")) } diff --git a/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt index bc07190ea21..448c5453f40 100644 --- a/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/simpleWithHandleResult.kt @@ -1,6 +1,6 @@ class Controller { var res = 0 - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt b/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt index d12f254df89..67f4df07d0c 100644 --- a/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt +++ b/compiler/testData/codegen/box/coroutines/statementLikeLastExpression.kt @@ -1,6 +1,6 @@ var globalResult = "" class Controller { - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) } diff --git a/compiler/testData/codegen/box/coroutines/suspendDelegation.kt b/compiler/testData/codegen/box/coroutines/suspendDelegation.kt index 81d31ab79e1..b371ff3f03e 100644 --- a/compiler/testData/codegen/box/coroutines/suspendDelegation.kt +++ b/compiler/testData/codegen/box/coroutines/suspendDelegation.kt @@ -1,9 +1,7 @@ class Controller { - suspend fun suspendHere(x: Continuation) { - suspendThere(x) - } + suspend fun suspendHere(): String = suspendThere() - suspend fun suspendThere(x: Continuation) { + suspend fun suspendThere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/suspendExtension.kt b/compiler/testData/codegen/box/coroutines/suspendExtension.kt index 4e3e9532c52..209bf4a5a24 100644 --- a/compiler/testData/codegen/box/coroutines/suspendExtension.kt +++ b/compiler/testData/codegen/box/coroutines/suspendExtension.kt @@ -1,23 +1,17 @@ @AllowSuspendExtensions class Controller { - suspend fun String.suspendHere(x: Continuation) { + suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume(this) } - inline suspend fun String.inlineSuspendHere(x: Continuation) { - suspendHere(x) - } + inline suspend fun String.inlineSuspendHere(): String = suspendHere() // INTERCEPT_RESUME_PLACEHOLDER } -suspend fun Controller.suspendExtension(v: String, x: Continuation) { - v.suspendHere(x) -} +suspend fun Controller.suspendExtension(v: String): String = v.suspendHere() -inline suspend fun Controller.inlineSuspendExtension(v: String, x: Continuation) { - v.inlineSuspendHere(x) -} +inline suspend fun Controller.inlineSuspendExtension(v: String): String = v.inlineSuspendHere() fun builder(coroutine c: Controller.() -> Continuation) { c(Controller()).resume(Unit) diff --git a/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt b/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt index f8dc2ce4a00..58ad94076b4 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFromInlineLambda.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(v: Int, x: Continuation) { + suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x -> x.resume(v * 2) } diff --git a/compiler/testData/codegen/box/coroutines/suspendInCycle.kt b/compiler/testData/codegen/box/coroutines/suspendInCycle.kt index 977f16eda70..d1363754a15 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInCycle.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInCycle.kt @@ -1,9 +1,9 @@ class Controller { var i = 0 - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x -> x.resume(i++) } - suspend fun suspendThere(x: Continuation) { + suspend fun suspendThere(): String = suspendWithCurrentContinuation { x -> x.resume("?") } diff --git a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt index 99bb5c89253..fcbe2cb0f45 100644 --- a/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt +++ b/compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt @@ -1,13 +1,13 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("K") } - suspend fun suspendWithArgument(v: String, x: Continuation) { + suspend fun suspendWithArgument(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) } - suspend fun suspendWithDouble(v: Double, x: Continuation) { + suspend fun suspendWithDouble(v: Double): Double = suspendWithCurrentContinuation { x -> x.resume(v) } diff --git a/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt index 590325fb0d6..49c15d1a70b 100644 --- a/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryCatchFinallyWithHandleResult.kt @@ -4,13 +4,13 @@ var wasCalled = false class Controller { val postponedActions = ArrayList<() -> Unit>() - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resume(v) } } - suspend fun suspendWithException(e: Exception, x: Continuation) { + suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } diff --git a/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt index 6c32812b848..2f845801715 100644 --- a/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryCatchWithHandleResult.kt @@ -4,13 +4,13 @@ var wasCalled = false class Controller { val postponedActions = ArrayList<() -> Unit>() - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resume(v) } } - suspend fun suspendWithException(e: Exception, x: Continuation) { + suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt index 8be989f0d34..6c4f60afe66 100644 --- a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt +++ b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(v: String, x: Continuation) { + suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x -> x.resume(v) } diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt b/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt index 395056e9ab3..66e3ea39f16 100644 --- a/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt +++ b/compiler/testData/codegen/box/coroutines/tryFinallyWithHandleResult.kt @@ -4,13 +4,13 @@ var wasCalled = false class Controller { val postponedActions = mutableListOf<() -> Unit>() - suspend fun suspendWithValue(v: String, x: Continuation) { + suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resume(v) } } - suspend fun suspendWithException(e: Exception, x: Continuation) { + suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x -> postponedActions.add { x.resumeWithException(e) } diff --git a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt index 04d0d082b8a..29fc982959b 100644 --- a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt +++ b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTable.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt index b77bf58abd4..400e94a382f 100644 --- a/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt +++ b/compiler/testData/codegen/box/coroutines/varValueConflictsWithTableSameSort.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } diff --git a/compiler/testData/codegen/box/reflection/modifiers/functions.kt b/compiler/testData/codegen/box/reflection/modifiers/functions.kt index 2e5761344f5..b6e3c43a230 100644 --- a/compiler/testData/codegen/box/reflection/modifiers/functions.kt +++ b/compiler/testData/codegen/box/reflection/modifiers/functions.kt @@ -10,7 +10,8 @@ inline fun inline() {} class External { external fun external() } operator fun Unit.invoke() {} infix fun Unit.infix(unit: Unit) {} -class Suspend { suspend fun suspend(c: Continuation) {} } +// TODO: support or prohibit references to suspend functions +// class Suspend { suspend fun suspend(c: Continuation) {} } val externalGetter = Unit external get @@ -44,11 +45,11 @@ fun box(): String { assertTrue(Unit::infix.isInfix) assertFalse(Unit::infix.isSuspend) - assertFalse(Suspend::suspend.isInline) - assertFalse(Suspend::suspend.isExternal) - assertFalse(Suspend::suspend.isOperator) - assertFalse(Suspend::suspend.isInfix) - assertTrue(Suspend::suspend.isSuspend) +// assertFalse(Suspend::suspend.isInline) +// assertFalse(Suspend::suspend.isExternal) +// assertFalse(Suspend::suspend.isOperator) +// assertFalse(Suspend::suspend.isInfix) +// assertTrue(Suspend::suspend.isSuspend) assertTrue(::externalGetter.getter.isExternal) assertFalse(::externalGetter.getter.isInline) diff --git a/compiler/testData/codegen/bytecodeListing/coroutineFields.kt b/compiler/testData/codegen/bytecodeListing/coroutineFields.kt index d7234d1685d..d638c2c0131 100644 --- a/compiler/testData/codegen/bytecodeListing/coroutineFields.kt +++ b/compiler/testData/codegen/bytecodeListing/coroutineFields.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere() = suspendWithCurrentContinuation { x -> x.resume("OK") } } diff --git a/compiler/testData/codegen/bytecodeText/constCoroutine.kt b/compiler/testData/codegen/bytecodeText/constCoroutine.kt index d1c1a02e2d4..e2324a99a4f 100644 --- a/compiler/testData/codegen/bytecodeText/constCoroutine.kt +++ b/compiler/testData/codegen/bytecodeText/constCoroutine.kt @@ -1,6 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { - } + suspend fun suspendHere() = "" } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/complicatedMerge.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/complicatedMerge.kt index 91c1e73f246..8972b652060 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/complicatedMerge.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/complicatedMerge.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/i2bResult.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/i2bResult.kt index e418af58b4a..4a8fd563eb3 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/i2bResult.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/i2bResult.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt index e355ea9b293..9f3aa0d3d41 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromByteArray.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromByteArray.kt index d6836ba66ff..e1e22943094 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromByteArray.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/loadFromByteArray.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/noVariableInTable.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/noVariableInTable.kt index 521f6ba6b01..4a7cfd6537e 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/noVariableInTable.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/noVariableInTable.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt index 6fe01877767..6fa2ff81a9a 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/sameIconst1ManyVars.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInArrayStore.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInArrayStore.kt index 69e628ff83c..24045035bbb 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInArrayStore.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInArrayStore.kt @@ -1,6 +1,6 @@ // WITH_RUNTIME class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInMethodCall.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInMethodCall.kt index 29d2540f1d9..75423fd16b1 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInMethodCall.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInMethodCall.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInPutfield.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInPutfield.kt index e2701da4815..628edd90881 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInPutfield.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInPutfield.kt @@ -1,6 +1,6 @@ // WITH_RUNTIME class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInVarStore.kt b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInVarStore.kt index 855669e9e63..e08059f341e 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInVarStore.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/intLikeVarSpilling/usedInVarStore.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x -> x.resume(Unit) } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTable.kt b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTable.kt index 5578a8a0ecf..8336b1d2334 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTable.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTable.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } } diff --git a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt index a5bf8f07b4e..d73aa0c6d62 100644 --- a/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt +++ b/compiler/testData/codegen/bytecodeText/coroutines/varValueConflictsWithTableSameSort.kt @@ -1,5 +1,5 @@ class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere(): String = suspendWithCurrentContinuation { x -> x.resume("OK") } } diff --git a/compiler/testData/codegen/java8/box/async.kt b/compiler/testData/codegen/java8/box/async.kt index a857832feef..2d042e9fa80 100644 --- a/compiler/testData/codegen/java8/box/async.kt +++ b/compiler/testData/codegen/java8/box/async.kt @@ -53,7 +53,7 @@ class FutureController { val future = CompletableFuture() - suspend fun await(f: CompletableFuture, machine: Continuation) { + suspend fun await(f: CompletableFuture) = suspendWithCurrentContinuation { machine -> f.whenComplete { value, throwable -> if (throwable == null) machine.resume(value) diff --git a/compiler/testData/codegen/java8/box/asyncException.kt b/compiler/testData/codegen/java8/box/asyncException.kt index aabc3232801..2de61e85c48 100644 --- a/compiler/testData/codegen/java8/box/asyncException.kt +++ b/compiler/testData/codegen/java8/box/asyncException.kt @@ -49,7 +49,7 @@ fun async(coroutine c: FutureController.() -> Continuation): Comple class FutureController { val future = CompletableFuture() - suspend fun await(f: CompletableFuture, machine: Continuation) { + suspend fun await(f: CompletableFuture) = suspendWithCurrentContinuation { machine -> f.whenComplete { value, throwable -> if (throwable == null) machine.resume(value) diff --git a/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt b/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt index 82e9cac886b..74101e8817c 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/coroutinesBinary.kt @@ -1,7 +1,7 @@ // FILE: A.kt package a class Controller { - suspend fun suspendHere(x: Continuation) { + suspend fun suspendHere() = suspendWithCurrentContinuation { x -> x.resume("OK") } } diff --git a/jps-plugin/testData/incremental/inlineFunCallSite/coroutine/usage.kt b/jps-plugin/testData/incremental/inlineFunCallSite/coroutine/usage.kt index ed10ee21c2d..ec35bbd5b0c 100644 --- a/jps-plugin/testData/incremental/inlineFunCallSite/coroutine/usage.kt +++ b/jps-plugin/testData/incremental/inlineFunCallSite/coroutine/usage.kt @@ -5,7 +5,7 @@ fun async(coroutine x: Controller.() -> Continuation) { } class Controller { - suspend fun step(param: Int, next: Continuation) { + suspend fun step(param: Int) = suspendWithCurrentContinuation { next -> next.resume(param + 1) } }