Implement callable references to suspend functions
In FE they have type KSuspendFunctionN In BE they are treated like normal callable references with additional parameter in invoke function.
This commit is contained in:
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls
|
||||
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.contracts.EffectSystem
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
@@ -160,7 +161,8 @@ class CallCompleter(
|
||||
val expectedReturnType =
|
||||
if (call.isCallableReference()) {
|
||||
// TODO: compute generic type argument for R in the kotlin.Function<R> supertype (KT-12963)
|
||||
if (!TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) expectedType.getReturnTypeFromFunctionType()
|
||||
if (!TypeUtils.noExpectedType(expectedType) && (expectedType.isFunctionType || expectedType.isSuspendFunctionType))
|
||||
expectedType.getReturnTypeFromFunctionType()
|
||||
else TypeUtils.NO_EXPECTED_TYPE
|
||||
} else expectedType
|
||||
|
||||
@@ -211,7 +213,7 @@ class CallCompleter(
|
||||
}
|
||||
}
|
||||
|
||||
if (call.isCallableReference() && !TypeUtils.noExpectedType(expectedType) && expectedType.isFunctionType) {
|
||||
if (call.isCallableReference() && !TypeUtils.noExpectedType(expectedType) && (expectedType.isFunctionType || expectedType.isSuspendFunctionType)) {
|
||||
updateSystemIfNeeded { builder ->
|
||||
candidateDescriptor.valueParameters.zip(expectedType.getValueParameterTypesFromFunctionType())
|
||||
.forEach { (parameter, argument) ->
|
||||
|
||||
+6
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -59,6 +60,8 @@ object CoroutineSuspendCallChecker : CallChecker {
|
||||
it.ownerDescriptor.safeAs<FunctionDescriptor>()?.isSuspend == true
|
||||
}?.cast<LexicalScope>()?.ownerDescriptor?.cast<FunctionDescriptor>()
|
||||
|
||||
val isCallableReference = resolvedCall.call.callElement.parent is KtCallableReferenceExpression
|
||||
|
||||
when {
|
||||
enclosingSuspendFunction != null -> {
|
||||
val callElement = resolvedCall.call.callElement as KtExpression
|
||||
@@ -77,6 +80,9 @@ object CoroutineSuspendCallChecker : CallChecker {
|
||||
|
||||
checkRestrictsSuspension(enclosingSuspendFunction, resolvedCall, reportOn, context)
|
||||
}
|
||||
isCallableReference -> {
|
||||
// do nothing: we can get callable reference to suspend function outside suspend context
|
||||
}
|
||||
else -> {
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> context.trace.report(
|
||||
|
||||
+10
-4
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -45,6 +46,7 @@ import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.calls.util.createValueParametersForInvokeInFunctionType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
@@ -585,7 +587,7 @@ class DoubleColonExpressionResolver(
|
||||
Annotations.EMPTY,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
expression.toSourceElement(),
|
||||
/* isCoroutine = */ false
|
||||
/* isCoroutine = */ ReflectionTypes.isKSuspendFunction(type)
|
||||
)
|
||||
|
||||
functionDescriptor.initialize(
|
||||
@@ -636,8 +638,8 @@ class DoubleColonExpressionResolver(
|
||||
) {
|
||||
val descriptor =
|
||||
if (resolutionResults?.isSingleResult == true) resolutionResults.resultingDescriptor as? FunctionDescriptor else null
|
||||
if (descriptor?.isSuspend == true) {
|
||||
context.trace.report(UNSUPPORTED.on(expression.callableReference, "Callable references to suspend functions"))
|
||||
if (descriptor?.isSuspend == true && descriptor is PropertyDescriptor) {
|
||||
context.trace.report(UNSUPPORTED.on(expression.callableReference, "Callable references to suspend property"))
|
||||
}
|
||||
|
||||
val expressionResult = lhsResult as? DoubleColonLHS.Expression ?: return
|
||||
@@ -783,7 +785,11 @@ class DoubleColonExpressionResolver(
|
||||
val returnType = descriptor.returnType ?: return null
|
||||
val parametersTypes = descriptor.valueParameters.map { it.type }
|
||||
val parametersNames = descriptor.valueParameters.map { it.name }
|
||||
return reflectionTypes.getKFunctionType(
|
||||
return if (descriptor.isSuspend) reflectionTypes.getKSuspendFunctionType(
|
||||
Annotations.EMPTY, receiverType,
|
||||
parametersTypes, parametersNames, returnType, descriptor.builtIns
|
||||
)
|
||||
else reflectionTypes.getKFunctionType(
|
||||
Annotations.EMPTY, receiverType,
|
||||
parametersTypes, parametersNames, returnType, descriptor.builtIns
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user