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.Printer
|
||||||
import org.jetbrains.kotlin.utils.ThrowingList
|
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) {
|
private fun <D : CallableDescriptor> ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults<D>, trace: TemporaryTraceAndCache) {
|
||||||
when (this) {
|
when (this) {
|
||||||
ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS ->
|
ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS ->
|
||||||
@@ -159,28 +150,6 @@ fun resolvePossiblyAmbiguousCallableReference(
|
|||||||
return null
|
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<*>) {
|
private fun bindFunctionReference(expression: KtCallableReferenceExpression, type: KotlinType, context: ResolutionContext<*>) {
|
||||||
val functionDescriptor = AnonymousFunctionDescriptor(
|
val functionDescriptor = AnonymousFunctionDescriptor(
|
||||||
context.scope.ownerDescriptor,
|
context.scope.ownerDescriptor,
|
||||||
@@ -287,7 +256,7 @@ fun createReflectionTypeForResolvedCallableReference(
|
|||||||
fun getResolvedCallableReferenceShapeType(
|
fun getResolvedCallableReferenceShapeType(
|
||||||
reference: KtCallableReferenceExpression,
|
reference: KtCallableReferenceExpression,
|
||||||
lhsType: KotlinType?,
|
lhsType: KotlinType?,
|
||||||
overloadResolutionResults: OverloadResolutionResults<CallableDescriptor>?,
|
overloadResolutionResults: OverloadResolutionResults<*>?,
|
||||||
context: ResolutionContext<*>,
|
context: ResolutionContext<*>,
|
||||||
expectedTypeUnknown: Boolean,
|
expectedTypeUnknown: Boolean,
|
||||||
reflectionTypes: ReflectionTypes,
|
reflectionTypes: ReflectionTypes,
|
||||||
|
|||||||
+24
-16
@@ -17,11 +17,11 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls;
|
package org.jetbrains.kotlin.resolve.calls;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import kotlin.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
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.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.kotlin.types.expressions.*;
|
||||||
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
|
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
|
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -63,31 +63,36 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
|||||||
|
|
||||||
public class ArgumentTypeResolver {
|
public class ArgumentTypeResolver {
|
||||||
@NotNull private final TypeResolver typeResolver;
|
@NotNull private final TypeResolver typeResolver;
|
||||||
@NotNull private final CallResolver callResolver;
|
@NotNull private final DoubleColonExpressionResolver doubleColonExpressionResolver;
|
||||||
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
|
||||||
@NotNull private final KotlinBuiltIns builtIns;
|
@NotNull private final KotlinBuiltIns builtIns;
|
||||||
@NotNull private final ReflectionTypes reflectionTypes;
|
@NotNull private final ReflectionTypes reflectionTypes;
|
||||||
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
@NotNull private final FunctionPlaceholders functionPlaceholders;
|
@NotNull private final FunctionPlaceholders functionPlaceholders;
|
||||||
|
|
||||||
|
private ExpressionTypingServices expressionTypingServices;
|
||||||
|
|
||||||
public ArgumentTypeResolver(
|
public ArgumentTypeResolver(
|
||||||
@NotNull TypeResolver typeResolver,
|
@NotNull TypeResolver typeResolver,
|
||||||
@NotNull CallResolver callResolver,
|
@NotNull DoubleColonExpressionResolver doubleColonExpressionResolver,
|
||||||
@NotNull ExpressionTypingServices expressionTypingServices,
|
|
||||||
@NotNull KotlinBuiltIns builtIns,
|
@NotNull KotlinBuiltIns builtIns,
|
||||||
@NotNull ReflectionTypes reflectionTypes,
|
@NotNull ReflectionTypes reflectionTypes,
|
||||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||||
@NotNull FunctionPlaceholders functionPlaceholders
|
@NotNull FunctionPlaceholders functionPlaceholders
|
||||||
) {
|
) {
|
||||||
this.typeResolver = typeResolver;
|
this.typeResolver = typeResolver;
|
||||||
this.callResolver = callResolver;
|
this.doubleColonExpressionResolver = doubleColonExpressionResolver;
|
||||||
this.expressionTypingServices = expressionTypingServices;
|
|
||||||
this.builtIns = builtIns;
|
this.builtIns = builtIns;
|
||||||
this.reflectionTypes = reflectionTypes;
|
this.reflectionTypes = reflectionTypes;
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
this.functionPlaceholders = functionPlaceholders;
|
this.functionPlaceholders = functionPlaceholders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// component dependency cycle
|
||||||
|
@Inject
|
||||||
|
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
|
||||||
|
this.expressionTypingServices = expressionTypingServices;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isSubtypeOfForArgumentType(
|
public static boolean isSubtypeOfForArgumentType(
|
||||||
@NotNull KotlinType actualType,
|
@NotNull KotlinType actualType,
|
||||||
@NotNull KotlinType expectedType
|
@NotNull KotlinType expectedType
|
||||||
@@ -238,14 +243,17 @@ public class ArgumentTypeResolver {
|
|||||||
@NotNull CallResolutionContext<?> context,
|
@NotNull CallResolutionContext<?> context,
|
||||||
boolean expectedTypeIsUnknown
|
boolean expectedTypeIsUnknown
|
||||||
) {
|
) {
|
||||||
KotlinType receiverType =
|
Pair<DoubleColonLHS, OverloadResolutionResults<?>> pair =
|
||||||
CallableReferencesResolutionUtilsKt.resolveCallableReferenceReceiverType(callableReferenceExpression, context, typeResolver);
|
doubleColonExpressionResolver.resolveCallableReference(
|
||||||
OverloadResolutionResults<CallableDescriptor> overloadResolutionResults =
|
callableReferenceExpression,
|
||||||
CallableReferencesResolutionUtilsKt.resolvePossiblyAmbiguousCallableReference(
|
ExpressionTypingContext.newContext(context),
|
||||||
callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
|
SHAPE_FUNCTION_ARGUMENTS
|
||||||
callResolver);
|
);
|
||||||
|
DoubleColonLHS lhs = pair.getFirst();
|
||||||
|
|
||||||
|
KotlinType receiverType = lhs != null ? lhs.getType() : null;
|
||||||
return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType(
|
return CallableReferencesResolutionUtilsKt.getResolvedCallableReferenceShapeType(
|
||||||
callableReferenceExpression, receiverType, overloadResolutionResults, context, expectedTypeIsUnknown,
|
callableReferenceExpression, receiverType, pair.getSecond(), context, expectedTypeIsUnknown,
|
||||||
reflectionTypes, builtIns, functionPlaceholders
|
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.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.callableReferences.createReflectionTypeForResolvedCallableReference
|
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.CallExpressionResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
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.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
|
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.resolve.calls.util.FakeCallableDescriptorForObject
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -202,18 +205,18 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression, c: ExpressionTypingContext): KotlinTypeInfo {
|
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
|
val callableReference = expression.callableReference
|
||||||
if (callableReference.getReferencedName().isEmpty()) {
|
if (callableReference.getReferencedName().isEmpty()) {
|
||||||
|
expression.receiverExpression?.let { resolveDoubleColonLHS(it, expression, c) }
|
||||||
c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference))
|
c.trace.report(UNRESOLVED_REFERENCE.on(callableReference, callableReference))
|
||||||
val errorType = ErrorUtils.createErrorType("Empty callable reference")
|
val errorType = ErrorUtils.createErrorType("Empty callable reference")
|
||||||
return dataFlowAnalyzer.createCheckedTypeInfo(errorType, c, expression)
|
return dataFlowAnalyzer.createCheckedTypeInfo(errorType, c, expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
val trace = TemporaryBindingTrace.create(c.trace, "Callable reference type")
|
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)
|
val hasErrors = hasErrors(trace) // Do not inline this local variable (execution order is important)
|
||||||
trace.commit()
|
trace.commit()
|
||||||
if (!hasErrors && result != null) {
|
if (!hasErrors && result != null) {
|
||||||
@@ -257,18 +260,22 @@ class DoubleColonExpressionResolver(
|
|||||||
|
|
||||||
private fun getCallableReferenceType(
|
private fun getCallableReferenceType(
|
||||||
expression: KtCallableReferenceExpression,
|
expression: KtCallableReferenceExpression,
|
||||||
lhsType: KotlinType?,
|
lhs: DoubleColonLHS?,
|
||||||
isBound: Boolean,
|
resolutionResults: OverloadResolutionResults<*>?,
|
||||||
context: ExpressionTypingContext
|
context: ExpressionTypingContext
|
||||||
): KotlinType? {
|
): KotlinType? {
|
||||||
val reference = expression.callableReference
|
val reference = expression.callableReference
|
||||||
|
|
||||||
val resolved = BooleanArray(1)
|
val descriptor =
|
||||||
val descriptor = resolveCallableReferenceTarget(expression, lhsType, context, resolved, callResolver)
|
if (resolutionResults != null && !resolutionResults.isNothing) {
|
||||||
if (!resolved[0]) {
|
OverloadResolutionResultsUtil.getResultingCall(resolutionResults, context.contextDependency)?.let { call ->
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference))
|
call.resultingDescriptor
|
||||||
}
|
} ?: return null
|
||||||
if (descriptor == null) return null
|
}
|
||||||
|
else {
|
||||||
|
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (expression.isEmptyLHS &&
|
if (expression.isEmptyLHS &&
|
||||||
(descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null)) {
|
(descriptor.dispatchReceiverParameter != null || descriptor.extensionReceiverParameter != null)) {
|
||||||
@@ -283,7 +290,23 @@ class DoubleColonExpressionResolver(
|
|||||||
context.trace.report(CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR.on(reference))
|
context.trace.report(CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR.on(reference))
|
||||||
}
|
}
|
||||||
|
|
||||||
val ignoreReceiver = isBound || expression.isEmptyLHS
|
val ignoreReceiver = lhs is DoubleColonLHS.Expression || expression.isEmptyLHS
|
||||||
return createReflectionTypeForResolvedCallableReference(expression, lhsType, ignoreReceiver, descriptor, context, reflectionTypes)
|
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<!>
|
A::<!UNRESOLVED_REFERENCE!>bar<!>
|
||||||
|
|
||||||
<!UNRESOLVED_REFERENCE!>B<!>::<!OVERLOAD_RESOLUTION_AMBIGUITY!>bar<!>
|
<!UNRESOLVED_REFERENCE!>B<!>::<!UNRESOLVED_REFERENCE!>bar<!>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user