diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt index 36414130dce..75184a0658a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -181,24 +181,6 @@ fun resolveCallableReferenceTarget( } } -private fun createReflectionTypeForFunction( - descriptor: FunctionDescriptor, - receiverType: KotlinType?, - reflectionTypes: ReflectionTypes -): KotlinType? { - val returnType = descriptor.returnType ?: return null - val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters) - return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType) -} - -private fun createReflectionTypeForProperty( - descriptor: PropertyDescriptor, - receiverType: KotlinType?, - reflectionTypes: ReflectionTypes -): KotlinType { - return reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, descriptor.isVar) -} - private fun bindFunctionReference(expression: KtCallableReferenceExpression, type: KotlinType, context: ResolutionContext<*>) { val functionDescriptor = AnonymousFunctionDescriptor( context.scope.ownerDescriptor, @@ -230,7 +212,8 @@ private fun createReflectionTypeForCallableDescriptor( lhsType: KotlinType?, reflectionTypes: ReflectionTypes, trace: BindingTrace?, - reportOn: KtExpression? + reportOn: KtExpression?, + ignoreReceiver: Boolean ): KotlinType? { val extensionReceiver = descriptor.extensionReceiverParameter val dispatchReceiver = descriptor.dispatchReceiverParameter?.let { dispatchReceiver -> @@ -248,15 +231,19 @@ private fun createReflectionTypeForCallableDescriptor( } val receiverType = - if (extensionReceiver != null || dispatchReceiver != null) + if ((extensionReceiver != null || dispatchReceiver != null) && !ignoreReceiver) lhsType ?: extensionReceiver?.type ?: dispatchReceiver?.type else null return when (descriptor) { - is FunctionDescriptor -> - createReflectionTypeForFunction(descriptor, receiverType, reflectionTypes) - is PropertyDescriptor -> - createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes) + is FunctionDescriptor -> { + val returnType = descriptor.returnType ?: return null + val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.valueParameters) + return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType) + } + is PropertyDescriptor -> { + reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.type, descriptor.isVar) + } is VariableDescriptor -> { if (reportOn != null) { trace?.report(UNSUPPORTED.on(reportOn, "References to variables aren't supported yet")) @@ -270,9 +257,10 @@ private fun createReflectionTypeForCallableDescriptor( fun getReflectionTypeForCandidateDescriptor( descriptor: CallableDescriptor, - reflectionTypes: ReflectionTypes + reflectionTypes: ReflectionTypes, + ignoreReceiver: Boolean ): KotlinType? = - createReflectionTypeForCallableDescriptor(descriptor, null, reflectionTypes, null, null) + createReflectionTypeForCallableDescriptor(descriptor, null, reflectionTypes, null, null, ignoreReceiver) fun createReflectionTypeForResolvedCallableReference( reference: KtCallableReferenceExpression, @@ -282,7 +270,7 @@ fun createReflectionTypeForResolvedCallableReference( reflectionTypes: ReflectionTypes ): KotlinType? { val type = createReflectionTypeForCallableDescriptor( - descriptor, lhsType, reflectionTypes, context.trace, reference.getCallableReference() + descriptor, lhsType, reflectionTypes, context.trace, reference.callableReference, reference.typeReference == null ) ?: return null when (descriptor) { is FunctionDescriptor -> { @@ -310,7 +298,8 @@ fun getResolvedCallableReferenceShapeType( null overloadResolutionResults.isSingleResult -> OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call -> - createReflectionTypeForCallableDescriptor(call.resultingDescriptor, lhsType, reflectionTypes, context.trace, reference) + createReflectionTypeForCallableDescriptor(call.resultingDescriptor, lhsType, reflectionTypes, context.trace, reference, + reference.typeReference == null) } expectedTypeUnknown /* && overload resolution was ambiguous */ -> functionPlaceholders.createFunctionPlaceholderType(emptyList(), false) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 55bf5638841..679d91cdc35 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -157,8 +157,11 @@ class CandidateResolver( private fun CallCandidateResolutionContext.checkExpectedCallableType() = check { if (!noExpectedType(expectedType)) { - val candidate = candidateCall.getCandidateDescriptor() - val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, reflectionTypes); + val candidate = candidateCall.candidateDescriptor + val candidateReflectionType = getReflectionTypeForCandidateDescriptor( + candidate, reflectionTypes, + call.callElement.parent.let { it is KtCallableReferenceExpression && it.typeReference == null } + ); if (candidateReflectionType != null) { if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) { candidateCall.addStatus(OTHER_ERROR) diff --git a/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.kt b/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.kt index 7e77faf1255..fd68f9f7f28 100644 --- a/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.kt +++ b/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.kt @@ -1,6 +1,9 @@ // !CHECK_TYPE -import kotlin.reflect.KFunction1 +import kotlin.reflect.KFunction0 + +fun explicitlyExpectFunction0(f: () -> Unit) = f +fun explicitlyExpectFunction1(f: (A) -> Unit) = f fun foo() {} @@ -10,6 +13,12 @@ class A { fun main() { val x = ::foo - checkSubtype>(x) + checkSubtype>(x) + + explicitlyExpectFunction0(x) + explicitlyExpectFunction1(x) + + explicitlyExpectFunction0(::foo) + explicitlyExpectFunction1(::foo) } } diff --git a/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.txt b/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.txt index 1f447e81c5a..a3758aeff4a 100644 --- a/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.txt +++ b/compiler/testData/diagnostics/tests/callableReference/function/noAmbiguityMemberVsTopLevel.txt @@ -1,5 +1,7 @@ package +public fun explicitlyExpectFunction0(/*0*/ f: () -> kotlin.Unit): () -> kotlin.Unit +public fun explicitlyExpectFunction1(/*0*/ f: (A) -> kotlin.Unit): (A) -> kotlin.Unit public fun foo(): kotlin.Unit public final class A { diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt index add78165b7d..4716ec73701 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/smart/Utils.kt @@ -248,7 +248,9 @@ private fun MutableCollection.addLookupElementsForNullable(factor fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade): FuzzyType? { if (!CallType.CALLABLE_REFERENCE.descriptorKindFilter.accepts(this)) return null // not supported by callable references - return getReflectionTypeForCandidateDescriptor(this, resolutionFacade.getFrontendService(ReflectionTypes::class.java))?.toFuzzyType(emptyList()) + return getReflectionTypeForCandidateDescriptor( + this, resolutionFacade.getFrontendService(ReflectionTypes::class.java), false + )?.toFuzzyType(emptyList()) } enum class SmartCompletionItemPriority {