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:
Ilmir Usmanov
2018-07-03 16:06:41 +03:00
parent eea95441c5
commit 28ad498956
31 changed files with 259 additions and 292 deletions
@@ -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.
}
@@ -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;
@@ -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()) {
@@ -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();