diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index ae0f08ac456..ba44c25d6bb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -60,6 +60,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; +import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; @@ -156,24 +157,12 @@ public class ExpressionCodegen extends KtVisitor impleme this.v = new InstructionAdapter(mv); this.myFrameMap = frameMap; this.context = context; - - FunctionDescriptor originalSuspendDescriptor = getOriginalSuspendDescriptor(context); - if (originalSuspendDescriptor != null && originalSuspendDescriptor.getReturnType() != null) { - this.returnType = getBoxedReturnTypeForSuspend(originalSuspendDescriptor); - } - else { - this.returnType = returnType; - } + this.returnType = returnType; this.parentCodegen = parentCodegen; this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state); } - @NotNull - private static Type getBoxedReturnTypeForSuspend(FunctionDescriptor descriptorForSuspend) { - return AsmTypes.OBJECT_TYPE; - } - @Nullable private static FunctionDescriptor getOriginalSuspendDescriptor(MethodContext context) { FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context); @@ -2236,7 +2225,7 @@ public class ExpressionCodegen extends KtVisitor impleme FunctionDescriptor containingFunction = BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst(); //FIRST_FUN_LABEL to prevent clashing with existing labels - return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL); + return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.FIRST_FUN_LABEL); } else { //local return null; @@ -2248,25 +2237,18 @@ public class ExpressionCodegen extends KtVisitor impleme DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element); assert element != null : "Expression should be not null " + expression.getText(); assert elementDescriptor != null : "Descriptor should be not null: " + element.getText(); - return new NonLocalReturnInfo(getReturnTypeForNonLocalReturn(elementDescriptor), expression.getLabelName()); + return new NonLocalReturnInfo(typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName()); } } return null; } - @NotNull - private Type getReturnTypeForNonLocalReturn(DeclarationDescriptor elementDescriptor) { - return elementDescriptor instanceof FunctionDescriptor && ((FunctionDescriptor) elementDescriptor).isSuspend() - ? getBoxedReturnTypeForSuspend((FunctionDescriptor) elementDescriptor) - : typeMapper.mapReturnType((CallableDescriptor) elementDescriptor); - } - public void returnExpression(KtExpression expr) { boolean isBlockedNamedFunction = expr instanceof KtBlockExpression && expr.getParent() instanceof KtNamedFunction; FunctionDescriptor originalCoroutineDescriptor = getOriginalCoroutineDescriptor(context); boolean isVoidCoroutineLambda = - originalCoroutineDescriptor != null && typeMapper.mapReturnType(originalCoroutineDescriptor).getSort() == Type.VOID; + originalCoroutineDescriptor != null && TypeSignatureMappingKt.hasVoidReturnType(originalCoroutineDescriptor); // If generating body for named block-bodied function or Unit-typed coroutine lambda, generate it as sequence of statements Type typeForExpression = @@ -2796,21 +2778,7 @@ public class ExpressionCodegen extends KtVisitor impleme Callable callable = resolveToCallable(fd, superCallTarget != null, resolvedCall); - - StackValue result = callable.invokeMethodWithArguments(resolvedCall, receiver, this); - - if (resolvedCall.getResultingDescriptor() instanceof FunctionDescriptor && - ((FunctionDescriptor) resolvedCall.getResultingDescriptor()).isSuspend() && - !CoroutineCodegenUtilKt.isSuspensionPointInStateMachine(resolvedCall, bindingContext)) { - // Suspend function's tail calls inside another suspend function should behave like they leave values of correct type, - // while real methods return java/lang/Object. - // NB: They are always in return position at the moment. - // If we didn't do this, StackValue.coerce would add proper CHECKCAST that would've failed in case of callee function - // returning SUSPENDED marker, which is instance of java/lang/Object. - return new OperationStackValue(returnType, ((OperationStackValue) result).getLambda()); - } - - return result; + return callable.invokeMethodWithArguments(resolvedCall, receiver, this); } private StackValue getContinuationParameterFromEnclosingSuspendFunction(@NotNull ResolvedCall resolvedCall) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index c453b7bcf01..eeb7dbc65ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor; import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.binding.MutableClosure; +import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt; import org.jetbrains.kotlin.codegen.signature.AsmTypeFactory; import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter; @@ -377,6 +378,12 @@ public class KotlinTypeMapper { return Type.VOID_TYPE; } + if (descriptor instanceof SimpleFunctionDescriptor && ((SimpleFunctionDescriptor) descriptor).isSuspend() && + ((SimpleFunctionDescriptor) descriptor).getUserData( + CoroutineCodegenUtilKt.INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) == null) { + return mapReturnType(CoroutineCodegenUtilKt.createJvmSuspendFunctionView((SimpleFunctionDescriptor) descriptor), sw); + } + if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) { if (sw != null) { sw.writeAsmType(Type.VOID_TYPE);