Use AnonymousFunctionDescriptor for suspend callable references
Also use it for local suspend functions, which allows us to remove hack with dropSuspend. Regenerate tests.
This commit is contained in:
@@ -1124,7 +1124,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (!isCrossinlineLambda) {
|
||||
v.aconst(null);
|
||||
}
|
||||
} else if (superClass != null && superClass.equals(state.getJvmRuntimeTypes().getFunctionReference())) {
|
||||
} else if (DescriptorUtilsKt.isCallableReferenceToSuspend(classDescriptor, state.getJvmRuntimeTypes().getFunctionReference())) {
|
||||
// Constructor of callable reference to suspend function does not accept continuation:
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
+4
-8
@@ -11,7 +11,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -31,8 +30,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.addFakeContinuationMarker;
|
||||
|
||||
/*
|
||||
* Notice the difference between two function descriptors in this class.
|
||||
* - [referencedFunction] is the function declaration which is referenced by the "::" expression. This is a real function present in code.
|
||||
@@ -69,14 +66,13 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
) {
|
||||
super(state);
|
||||
this.resolvedCall = resolvedCall;
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
if (resultingDescriptor instanceof FunctionDescriptor && ((FunctionDescriptor) resultingDescriptor).isSuspend()) {
|
||||
this.referencedFunction =
|
||||
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView((FunctionDescriptor) resultingDescriptor, state);
|
||||
FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
|
||||
if (referencedFunction.isSuspend()) {
|
||||
this.referencedFunction = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(referencedFunction, state);
|
||||
this.functionDescriptor = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(functionDescriptor, state);
|
||||
}
|
||||
else {
|
||||
this.referencedFunction = (FunctionDescriptor) resultingDescriptor;
|
||||
this.referencedFunction = referencedFunction;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
}
|
||||
this.receiverType = receiverType;
|
||||
|
||||
+7
-23
@@ -334,19 +334,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
nameStack.push(name);
|
||||
|
||||
if (CoroutineUtilKt.isSuspendLambda(functionDescriptor)) {
|
||||
SimpleFunctionDescriptor jvmSuspendFunctionView =
|
||||
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
|
||||
(SimpleFunctionDescriptor) functionDescriptor,
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
);
|
||||
|
||||
bindingTrace.record(
|
||||
CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW,
|
||||
functionDescriptor,
|
||||
jvmSuspendFunctionView
|
||||
);
|
||||
closure.setSuspend(true);
|
||||
closure.setSuspendLambda();
|
||||
createAndRecordSuspendFunctionView(closure, (SimpleFunctionDescriptor) functionDescriptor, true);
|
||||
}
|
||||
functionsStack.push(functionDescriptor);
|
||||
|
||||
@@ -406,8 +394,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
if (callableDescriptor instanceof SimpleFunctionDescriptor) {
|
||||
SimpleFunctionDescriptor functionDescriptor = (SimpleFunctionDescriptor) callableDescriptor;
|
||||
if (functionDescriptor.isSuspend()){
|
||||
createAndRecordSuspendFunctionView(closure, functionDescriptor, /* isSuspendLambda */ false, /* isDropSuspend */ false);
|
||||
if (functionDescriptor.isSuspend()) {
|
||||
createAndRecordSuspendFunctionView(closure, functionDescriptor, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,15 +409,13 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
private SimpleFunctionDescriptor createAndRecordSuspendFunctionView(
|
||||
MutableClosure closure,
|
||||
SimpleFunctionDescriptor functionDescriptor,
|
||||
boolean isSuspendLambda,
|
||||
boolean isDropSuspend
|
||||
boolean isSuspendLambda
|
||||
) {
|
||||
SimpleFunctionDescriptor jvmSuspendFunctionView =
|
||||
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
|
||||
functionDescriptor,
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
|
||||
this.bindingContext,
|
||||
isDropSuspend
|
||||
this.bindingContext
|
||||
);
|
||||
|
||||
bindingTrace.record(
|
||||
@@ -581,8 +567,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
MutableClosure closure = recordClosure(classDescriptor, name);
|
||||
|
||||
SimpleFunctionDescriptor jvmSuspendFunctionView =
|
||||
createAndRecordSuspendFunctionView(closure, (SimpleFunctionDescriptor) functionDescriptor,
|
||||
/* isSuspendLambda*/ false, /* isDropSuspend */ false);
|
||||
createAndRecordSuspendFunctionView(closure, (SimpleFunctionDescriptor) functionDescriptor, false);
|
||||
|
||||
// This is a very subtle place (hack).
|
||||
// When generating bytecode of some suspend function, we replace the original descriptor
|
||||
@@ -626,8 +611,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
nameStack.push(name);
|
||||
|
||||
if (functionDescriptor instanceof SimpleFunctionDescriptor && functionDescriptor.isSuspend()) {
|
||||
createAndRecordSuspendFunctionView(closure, (SimpleFunctionDescriptor) functionDescriptor,
|
||||
/* isSuspendLambda */ true, /* isDropSuspend */ true);
|
||||
createAndRecordSuspendFunctionView(closure, (SimpleFunctionDescriptor) functionDescriptor,true);
|
||||
}
|
||||
|
||||
functionsStack.push(functionDescriptor);
|
||||
|
||||
@@ -139,19 +139,26 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
private lateinit var constructorToUseFromInvoke: Method
|
||||
|
||||
private val createCoroutineDescriptor =
|
||||
funDescriptor.createCustomCopy {
|
||||
setName(Name.identifier(SUSPEND_FUNCTION_CREATE_METHOD_NAME))
|
||||
setReturnType(
|
||||
funDescriptor.module.getContinuationOfTypeOrAny(
|
||||
builtIns.unitType,
|
||||
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
)
|
||||
)
|
||||
// 'create' method should not inherit initial descriptor for suspend function from original descriptor
|
||||
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, null)
|
||||
setVisibility(Visibilities.PUBLIC)
|
||||
}
|
||||
private val createCoroutineDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
funDescriptor.containingDeclaration,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier(SUSPEND_FUNCTION_CREATE_METHOD_NAME),
|
||||
funDescriptor.kind,
|
||||
funDescriptor.source
|
||||
).also {
|
||||
it.initialize(
|
||||
funDescriptor.extensionReceiverParameter?.type,
|
||||
funDescriptor.dispatchReceiverParameter,
|
||||
funDescriptor.typeParameters,
|
||||
funDescriptor.valueParameters,
|
||||
funDescriptor.module.getContinuationOfTypeOrAny(
|
||||
builtIns.unitType,
|
||||
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
),
|
||||
funDescriptor.modality,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
}
|
||||
|
||||
override fun generateClosureBody() {
|
||||
for (parameter in allFunctionParameters()) {
|
||||
|
||||
+1
-5
@@ -214,8 +214,7 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(function: D, stat
|
||||
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
|
||||
function: D,
|
||||
isReleaseCoroutines: Boolean,
|
||||
bindingContext: BindingContext? = null,
|
||||
dropSuspend: Boolean = false
|
||||
bindingContext: BindingContext? = null
|
||||
): D {
|
||||
assert(function.isSuspend) {
|
||||
"Suspended function is expected, but $function was found"
|
||||
@@ -245,9 +244,6 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
|
||||
setPreserveSourceElement()
|
||||
setReturnType(function.builtIns.nullableAnyType)
|
||||
setValueParameters(it.valueParameters + continuationParameter)
|
||||
if (dropSuspend) {
|
||||
setIsSuspend(false)
|
||||
}
|
||||
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1016,7 +1016,7 @@ public class KotlinTypeMapper {
|
||||
|
||||
return OperatorNameConventions.INVOKE.asString();
|
||||
}
|
||||
else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor) || isSuspendFunctionReference(descriptor)) {
|
||||
else if (isLocalFunction(descriptor) || isFunctionExpression(descriptor)) {
|
||||
return OperatorNameConventions.INVOKE.asString();
|
||||
}
|
||||
else {
|
||||
@@ -1024,13 +1024,6 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSuspendFunctionReference(FunctionDescriptor descriptor) {
|
||||
return descriptor instanceof SimpleFunctionDescriptor &&
|
||||
descriptor.getName().isSpecial() &&
|
||||
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(descriptor) != null &&
|
||||
CoroutineCodegenUtilKt.unwrapInitialDescriptorForSuspendFunction(descriptor).isSuspend();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static OwnerKind getKindForDefaultImplCall(@NotNull FunctionDescriptor baseMethodDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = baseMethodDescriptor.getContainingDeclaration();
|
||||
|
||||
Reference in New Issue
Block a user