Extract method to fully or partially resolve callable reference
Reuse it in the main type-checking path in DoubleColonExpressionResolver, as well as in ArgumentTypeResolver which handles the case when a callable reference appears as an argument to another call
This commit is contained in:
+1
-32
@@ -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 <D : CallableDescriptor> ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults<D>, 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<CallableDescriptor>?,
|
||||
overloadResolutionResults: OverloadResolutionResults<*>?,
|
||||
context: ResolutionContext<*>,
|
||||
expectedTypeUnknown: Boolean,
|
||||
reflectionTypes: ReflectionTypes,
|
||||
|
||||
+24
-16
@@ -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<CallableDescriptor> overloadResolutionResults =
|
||||
CallableReferencesResolutionUtilsKt.resolvePossiblyAmbiguousCallableReference(
|
||||
callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
|
||||
callResolver);
|
||||
Pair<DoubleColonLHS, OverloadResolutionResults<?>> 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
|
||||
);
|
||||
}
|
||||
|
||||
+38
-15
@@ -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<DoubleColonLHS?, OverloadResolutionResults<*>?> {
|
||||
val lhsResult = expression.receiverExpression?.let { resolveDoubleColonLHS(it, expression, context) }
|
||||
|
||||
val resolutionResults = resolvePossiblyAmbiguousCallableReference(
|
||||
expression, lhsResult?.type, context, resolveArgumentsMode, callResolver
|
||||
)
|
||||
|
||||
return lhsResult to resolutionResults
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,5 +8,5 @@ fun main() {
|
||||
|
||||
A::<!UNRESOLVED_REFERENCE!>bar<!>
|
||||
|
||||
<!UNRESOLVED_REFERENCE!>B<!>::<!OVERLOAD_RESOLUTION_AMBIGUITY!>bar<!>
|
||||
}
|
||||
<!UNRESOLVED_REFERENCE!>B<!>::<!UNRESOLVED_REFERENCE!>bar<!>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user