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 f31b099f56b..7f2ff2b4e41 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/callableReferences/CallableReferencesResolutionUtils.kt @@ -53,15 +53,6 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.ThrowingList -fun resolveCallableReferenceReceiverType( - callableReferenceExpression: KtCallableReferenceExpression, - context: ResolutionContext<*>, - typeResolver: TypeResolver -): KotlinType? = - callableReferenceExpression.typeReference?.let { - typeResolver.resolveType(context.scope, it, context.trace, false) - } - private fun ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults, trace: TemporaryTraceAndCache) { when (this) { ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS -> @@ -159,28 +150,6 @@ fun resolvePossiblyAmbiguousCallableReference( return null } -fun resolveCallableReferenceTarget( - callableReferenceExpression: KtCallableReferenceExpression, - lhsType: KotlinType?, - context: ResolutionContext<*>, - resolvedToSomething: BooleanArray, - callResolver: CallResolver -): CallableDescriptor? { - val resolutionResults = resolvePossiblyAmbiguousCallableReference( - callableReferenceExpression, lhsType, context, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS, callResolver) - return resolutionResults?.let { results -> - if (results.isSomething()) { - resolvedToSomething[0] = true - OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency)?.let { call -> - call.resultingDescriptor - } - } - else { - null - } - } -} - private fun bindFunctionReference(expression: KtCallableReferenceExpression, type: KotlinType, context: ResolutionContext<*>) { val functionDescriptor = AnonymousFunctionDescriptor( context.scope.ownerDescriptor, @@ -287,7 +256,7 @@ fun createReflectionTypeForResolvedCallableReference( fun getResolvedCallableReferenceShapeType( reference: KtCallableReferenceExpression, lhsType: KotlinType?, - overloadResolutionResults: OverloadResolutionResults?, + overloadResolutionResults: OverloadResolutionResults<*>?, context: ResolutionContext<*>, expectedTypeUnknown: Boolean, reflectionTypes: ReflectionTypes, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java index 3cd8aef7e34..d5eeff0bb70 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java @@ -17,11 +17,11 @@ package org.jetbrains.kotlin.resolve.calls; import com.google.common.collect.Lists; +import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.ReflectionTypes; -import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.*; @@ -45,10 +45,10 @@ import org.jetbrains.kotlin.types.FunctionPlaceholdersKt; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; -import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices; -import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo; +import org.jetbrains.kotlin.types.expressions.*; import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt; +import javax.inject.Inject; import java.util.Collections; import java.util.List; @@ -63,31 +63,36 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; public class ArgumentTypeResolver { @NotNull private final TypeResolver typeResolver; - @NotNull private final CallResolver callResolver; - @NotNull private final ExpressionTypingServices expressionTypingServices; + @NotNull private final DoubleColonExpressionResolver doubleColonExpressionResolver; @NotNull private final KotlinBuiltIns builtIns; @NotNull private final ReflectionTypes reflectionTypes; @NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator; @NotNull private final FunctionPlaceholders functionPlaceholders; + private ExpressionTypingServices expressionTypingServices; + public ArgumentTypeResolver( @NotNull TypeResolver typeResolver, - @NotNull CallResolver callResolver, - @NotNull ExpressionTypingServices expressionTypingServices, + @NotNull DoubleColonExpressionResolver doubleColonExpressionResolver, @NotNull KotlinBuiltIns builtIns, @NotNull ReflectionTypes reflectionTypes, @NotNull ConstantExpressionEvaluator constantExpressionEvaluator, @NotNull FunctionPlaceholders functionPlaceholders ) { this.typeResolver = typeResolver; - this.callResolver = callResolver; - this.expressionTypingServices = expressionTypingServices; + this.doubleColonExpressionResolver = doubleColonExpressionResolver; this.builtIns = builtIns; this.reflectionTypes = reflectionTypes; this.constantExpressionEvaluator = constantExpressionEvaluator; this.functionPlaceholders = functionPlaceholders; } + // component dependency cycle + @Inject + public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) { + this.expressionTypingServices = expressionTypingServices; + } + public static boolean isSubtypeOfForArgumentType( @NotNull KotlinType actualType, @NotNull KotlinType expectedType @@ -238,14 +243,17 @@ public class ArgumentTypeResolver { @NotNull CallResolutionContext context, boolean expectedTypeIsUnknown ) { - KotlinType receiverType = - CallableReferencesResolutionUtilsKt.resolveCallableReferenceReceiverType(callableReferenceExpression, context, typeResolver); - OverloadResolutionResults overloadResolutionResults = - CallableReferencesResolutionUtilsKt.resolvePossiblyAmbiguousCallableReference( - callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS, - callResolver); + Pair> pair = + doubleColonExpressionResolver.resolveCallableReference( + callableReferenceExpression, + ExpressionTypingContext.newContext(context), + SHAPE_FUNCTION_ARGUMENTS + ); + DoubleColonLHS lhs = pair.getFirst(); + + KotlinType receiverType = lhs != null ? lhs.getType() : null; return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType( - callableReferenceExpression, receiverType, overloadResolutionResults, context, expectedTypeIsUnknown, + callableReferenceExpression, receiverType, pair.getSecond(), context, expectedTypeIsUnknown, reflectionTypes, builtIns, functionPlaceholders ); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index a14c36da88d..54095e0c4c2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -28,11 +28,14 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.callableReferences.createReflectionTypeForResolvedCallableReference -import org.jetbrains.kotlin.resolve.callableReferences.resolveCallableReferenceTarget +import org.jetbrains.kotlin.resolve.callableReferences.resolvePossiblyAmbiguousCallableReference import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver import org.jetbrains.kotlin.resolve.calls.CallResolver +import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache +import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults +import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType @@ -202,18 +205,18 @@ class DoubleColonExpressionResolver( } fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression, c: ExpressionTypingContext): KotlinTypeInfo { - val lhs = expression.receiverExpression?.let { resolveDoubleColonLHS(it, expression, c) } - val receiverType = lhs?.type // TODO: handle .Expression and .Type - val callableReference = expression.callableReference if (callableReference.getReferencedName().isEmpty()) { + expression.receiverExpression?.let { resolveDoubleColonLHS(it, expression, c) } c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference)) val errorType = ErrorUtils.createErrorType("Empty callable reference") return dataFlowAnalyzer.createCheckedTypeInfo(errorType, c, expression) } val trace = TemporaryBindingTrace.create(c.trace, "Callable reference type") - val result = getCallableReferenceType(expression, receiverType, lhs is DoubleColonLHS.Expression, c.replaceBindingTrace(trace)) + val context = c.replaceBindingTrace(trace) + val (lhs, resolutionResults) = resolveCallableReference(expression, context, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS) + val result = getCallableReferenceType(expression, lhs, resolutionResults, context) val hasErrors = hasErrors(trace) // Do not inline this local variable (execution order is important) trace.commit() if (!hasErrors && result != null) { @@ -257,18 +260,22 @@ class DoubleColonExpressionResolver( private fun getCallableReferenceType( expression: KtCallableReferenceExpression, - lhsType: KotlinType?, - isBound: Boolean, + lhs: DoubleColonLHS?, + resolutionResults: OverloadResolutionResults<*>?, context: ExpressionTypingContext ): KotlinType? { val reference = expression.callableReference - val resolved = BooleanArray(1) - val descriptor = resolveCallableReferenceTarget(expression, lhsType, context, resolved, callResolver) - if (!resolved[0]) { - context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference)) - } - if (descriptor == null) return null + val descriptor = + if (resolutionResults != null && !resolutionResults.isNothing) { + OverloadResolutionResultsUtil.getResultingCall(resolutionResults, context.contextDependency)?.let { call -> + call.resultingDescriptor + } ?: return null + } + else { + context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference)) + return null + } if (expression.isEmptyLHS && (descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null)) { @@ -283,7 +290,23 @@ class DoubleColonExpressionResolver( context.trace.report(CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR.on(reference)) } - val ignoreReceiver = isBound || expression.isEmptyLHS - return createReflectionTypeForResolvedCallableReference(expression, lhsType, ignoreReceiver, descriptor, context, reflectionTypes) + val ignoreReceiver = lhs is DoubleColonLHS.Expression || expression.isEmptyLHS + return createReflectionTypeForResolvedCallableReference( + expression, lhs?.type, ignoreReceiver, descriptor, context, reflectionTypes + ) + } + + fun resolveCallableReference( + expression: KtCallableReferenceExpression, + context: ExpressionTypingContext, + resolveArgumentsMode: ResolveArgumentsMode + ): Pair?> { + val lhsResult = expression.receiverExpression?.let { resolveDoubleColonLHS(it, expression, context) } + + val resolutionResults = resolvePossiblyAmbiguousCallableReference( + expression, lhsResult?.type, context, resolveArgumentsMode, callResolver + ) + + return lhsResult to resolutionResults } } diff --git a/compiler/testData/diagnostics/tests/callableReference/function/unresolved.kt b/compiler/testData/diagnostics/tests/callableReference/function/unresolved.kt index 64914488670..6e048684c12 100644 --- a/compiler/testData/diagnostics/tests/callableReference/function/unresolved.kt +++ b/compiler/testData/diagnostics/tests/callableReference/function/unresolved.kt @@ -8,5 +8,5 @@ fun main() { A::bar - B::bar -} \ No newline at end of file + B::bar +}