Support overload ambiguity resolution for callable references by expected type.

Resolve callable references taking into account expected callable types.

This affects call resolution procedure (resolve 'foo' in for 'foo(::bar)') similar to the approach used for function literals:

* During "shape arguments" phase of call resolution, callable references are resolved in independent context without expected type. If the callable reference is ambiguous, its shape type is a function placeholder type without parameter types and return type information. Otherwise, it is a reflection type for the resolved function or property. Upper-level call is resolved without taking into account ambiguous callable references.

* During "complete call" phase of call resolution, resolve callable reference arguments to actual descriptors (if possible), and update constraint system for the given call accordingly.

 #KT-6982 Fixed
 #KT-5780 Fixed
This commit is contained in:
Dmitry Petrov
2015-07-14 17:53:12 +03:00
parent b3a2ee2148
commit 6437a4bdc6
51 changed files with 1057 additions and 247 deletions
+2
View File
@@ -4,7 +4,9 @@
<option name="DEFAULT_COMPILER" value="Javac" />
<option name="BUILD_PROCESS_HEAP_SIZE" value="2000" />
<excludeFromCompile>
<directory url="file://$PROJECT_DIR$/core/reflection" includeSubdirectories="true" />
<directory url="file://$PROJECT_DIR$/core/reflection.jvm" includeSubdirectories="true" />
<directory url="file://$PROJECT_DIR$/core/reflection.stub.jvm" includeSubdirectories="true" />
</excludeFromCompile>
<resourceExtensions />
<wildcardResourcePatterns>
@@ -0,0 +1,276 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.resolve.callableReferences
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.context.*
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.utils.ThrowingList
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingComponents
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
public fun resolveCallableReferenceReceiverType(
callableReferenceExpression: JetCallableReferenceExpression,
context: ResolutionContext<*>,
typeResolver: TypeResolver
): JetType? =
callableReferenceExpression.getTypeReference()?.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 ->
if (results.isSingleResult()) trace.commit()
ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS ->
if (results.isSomething()) trace.commit()
}
}
private fun resolvePossiblyAmbiguousCallableReference(
reference: JetSimpleNameExpression,
receiver: ReceiverValue,
context: ResolutionContext<*>,
resolutionMode: ResolveArgumentsMode,
callResolver: CallResolver
): OverloadResolutionResults<CallableDescriptor> {
val call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.instance<ValueArgument>())
val temporaryTrace = TemporaryTraceAndCache.create(context, "trace to resolve ::${reference.getReferencedName()} as function", reference)
val newContext = if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
context.replaceTraceAndCache(temporaryTrace).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
else
context.replaceTraceAndCache(temporaryTrace)
val callResolutionContext = BasicCallResolutionContext.create(
newContext, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE)
val resolutionResults = callResolver.resolveCallForMember(reference, callResolutionContext)
resolutionMode.acceptResolution(resolutionResults, temporaryTrace)
return resolutionResults
}
private fun OverloadResolutionResults<*>.isSomething(): Boolean = !isNothing()
public fun resolvePossiblyAmbiguousCallableReference(
callableReferenceExpression: JetCallableReferenceExpression,
lhsType: JetType?,
context: ResolutionContext<*>,
resolutionMode: ResolveArgumentsMode,
callResolver: CallResolver
): OverloadResolutionResults<CallableDescriptor>? {
val reference = callableReferenceExpression.getCallableReference()
fun resolveInScope(traceTitle: String, scope: JetScope): OverloadResolutionResults<CallableDescriptor> {
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache).replaceScope(scope)
val results = resolvePossiblyAmbiguousCallableReference(reference, ReceiverValue.NO_RECEIVER, newContext, resolutionMode, callResolver)
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
return results
}
fun resolveWithReceiver(traceTitle: String, receiver: ReceiverValue): OverloadResolutionResults<CallableDescriptor> {
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache)
val results = resolvePossiblyAmbiguousCallableReference(reference, receiver, newContext, resolutionMode, callResolver)
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
return results
}
if (lhsType == null) {
return resolvePossiblyAmbiguousCallableReference(reference, ReceiverValue.NO_RECEIVER, context, resolutionMode, callResolver)
}
val classifier = lhsType.getConstructor().getDeclarationDescriptor()
if (classifier !is ClassDescriptor) {
context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(callableReferenceExpression))
return null
}
val possibleStatic = resolveInScope("trace to resolve ::${reference.getReferencedName()} in static scope", classifier.getStaticScope())
if (possibleStatic.isSomething()) return possibleStatic
val possibleNested = resolveInScope("trace to resolve ::${reference.getReferencedName()} in static nested classes scope",
DescriptorUtils.getStaticNestedClassesScope(classifier))
if (possibleNested.isSomething()) return possibleNested
val possibleWithReceiver = resolveWithReceiver("trace to resolve ::${reference.getReferencedName()} with receiver",
TransientReceiver(lhsType))
if (possibleWithReceiver.isSomething()) return possibleWithReceiver
return null
}
public fun resolveCallableReferenceTarget(
callableReferenceExpression: JetCallableReferenceExpression,
lhsType: JetType?,
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.getResultingDescriptor()
}
}
else {
null
}
}
}
private fun createReflectionTypeForFunction(
descriptor: FunctionDescriptor,
receiverType: JetType?,
reflectionTypes: ReflectionTypes
): JetType? {
val returnType = descriptor.getReturnType() ?: return null
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters())
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType)
}
private fun createReflectionTypeForProperty(
descriptor: PropertyDescriptor,
receiverType: JetType?,
reflectionTypes: ReflectionTypes
): JetType {
return reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.getType(), descriptor.isVar())
}
private fun bindFunctionReference(expression: JetCallableReferenceExpression, referenceType: JetType, context: ResolutionContext<*>) {
val functionDescriptor = AnonymousFunctionDescriptor(
context.scope.getContainingDeclaration(),
Annotations.EMPTY,
CallableMemberDescriptor.Kind.DECLARATION,
expression.toSourceElement())
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, referenceType, null, Modality.FINAL, Visibilities.PUBLIC)
context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor)
}
private fun bindPropertyReference(expression: JetCallableReferenceExpression, referenceType: JetType, context: ResolutionContext<*>) {
val localVariable = LocalVariableDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY, Name.special("<anonymous>"),
referenceType, /* mutable = */ false, expression.toSourceElement())
context.trace.record(BindingContext.VARIABLE, expression, localVariable)
}
private fun createReflectionTypeForCallableDescriptor(
descriptor: CallableDescriptor,
context: ResolutionContext<*>,
reflectionTypes: ReflectionTypes,
reportOn: JetExpression?
): JetType? {
val extensionReceiver = descriptor.getExtensionReceiverParameter()
val dispatchReceiver = descriptor.getDispatchReceiverParameter()
if (extensionReceiver != null && dispatchReceiver != null && descriptor is CallableMemberDescriptor) {
if (reportOn != null) {
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reportOn, descriptor))
}
return null
}
val receiverType = extensionReceiver?.getType() ?: dispatchReceiver?.getType()
return when (descriptor) {
is FunctionDescriptor ->
createReflectionTypeForFunction(descriptor, receiverType, reflectionTypes)
is PropertyDescriptor ->
createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes)
is VariableDescriptor -> {
if (reportOn != null) {
context.trace.report(UNSUPPORTED.on(reportOn, "References to variables aren't supported yet"))
}
null
}
else ->
throw UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: $descriptor")
}
}
public fun getReflectionTypeForCandidateDescriptor(
descriptor: CallableDescriptor,
context: ResolutionContext<*>,
reflectionTypes: ReflectionTypes
): JetType? =
createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, null)
public fun createReflectionTypeForResolvedCallableReference(
reference: JetCallableReferenceExpression,
descriptor: CallableDescriptor,
context: ResolutionContext<*>,
reflectionTypes: ReflectionTypes
): JetType? {
val type = createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, reference.getCallableReference())
?: return null
when (descriptor) {
is FunctionDescriptor -> {
bindFunctionReference(reference, type, context)
}
is PropertyDescriptor -> {
bindPropertyReference(reference, type, context)
}
}
return type
}
public fun getResolvedCallableReferenceShapeType(
reference: JetCallableReferenceExpression,
overloadResolutionResults: OverloadResolutionResults<CallableDescriptor>?,
context: ResolutionContext<*>,
expectedTypeUnknown: Boolean,
reflectionTypes: ReflectionTypes,
builtIns: KotlinBuiltIns
): JetType? =
when {
overloadResolutionResults == null ->
null
overloadResolutionResults.isSingleResult() ->
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call ->
createReflectionTypeForCallableDescriptor(call.getResultingDescriptor(), context, reflectionTypes, reference)
}
expectedTypeUnknown /* && overload resolution was ambiguous */ ->
ErrorUtils.createFunctionPlaceholderType(emptyList(), false)
else ->
builtIns.getFunctionType(Annotations.EMPTY, null, emptyList(), TypeUtils.DONT_CARE)
}
@@ -20,16 +20,20 @@ import com.google.common.collect.Lists;
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.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
@@ -60,17 +64,23 @@ 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 KotlinBuiltIns builtIns;
@NotNull private final ReflectionTypes reflectionTypes;
public ArgumentTypeResolver(
@NotNull KotlinBuiltIns builtIns,
@NotNull TypeResolver typeResolver,
@NotNull CallResolver callResolver,
@NotNull ExpressionTypingServices expressionTypingServices,
@NotNull TypeResolver typeResolver
@NotNull KotlinBuiltIns builtIns,
@NotNull ReflectionTypes reflectionTypes
) {
this.builtIns = builtIns;
this.expressionTypingServices = expressionTypingServices;
this.typeResolver = typeResolver;
this.callResolver = callResolver;
this.expressionTypingServices = expressionTypingServices;
this.builtIns = builtIns;
this.reflectionTypes = reflectionTypes;
}
public static boolean isSubtypeOfForArgumentType(
@@ -92,7 +102,7 @@ public class ArgumentTypeResolver {
@NotNull CallResolutionContext<?> context,
@NotNull ResolveArgumentsMode resolveFunctionArgumentBodies
) {
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
for (ValueArgument valueArgument : context.call.getValueArguments()) {
JetExpression argumentExpression = valueArgument.getArgumentExpression();
@@ -117,7 +127,7 @@ public class ArgumentTypeResolver {
}
public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull CallResolutionContext<?> context) {
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
for (ValueArgument valueArgument : context.call.getValueArguments()) {
JetExpression argumentExpression = valueArgument.getArgumentExpression();
@@ -148,7 +158,7 @@ public class ArgumentTypeResolver {
}
@Nullable
private static JetFunction getFunctionLiteralArgumentIfAny(
public static JetFunction getFunctionLiteralArgumentIfAny(
@NotNull JetExpression expression, @NotNull ResolutionContext context
) {
JetExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
@@ -181,6 +191,18 @@ public class ArgumentTypeResolver {
return deparenthesizedExpression;
}
@Nullable
public static JetCallableReferenceExpression getCallableReferenceExpressionIfAny(
@NotNull JetExpression expression,
@NotNull CallResolutionContext<?> context
) {
JetExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
if (deparenthesizedExpression instanceof JetCallableReferenceExpression) {
return (JetCallableReferenceExpression) deparenthesizedExpression;
}
return null;
}
@NotNull
public JetTypeInfo getArgumentTypeInfo(
@Nullable JetExpression expression,
@@ -190,18 +212,58 @@ public class ArgumentTypeResolver {
if (expression == null) {
return TypeInfoFactoryPackage.noTypeInfo(context);
}
if (isFunctionLiteralArgument(expression, context)) {
return getFunctionLiteralTypeInfo(expression, getFunctionLiteralArgument(expression, context), context, resolveArgumentsMode);
JetFunction functionLiteralArgument = getFunctionLiteralArgumentIfAny(expression, context);
if (functionLiteralArgument != null) {
return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode);
}
JetCallableReferenceExpression callableReferenceExpression = getCallableReferenceExpressionIfAny(expression, context);
if (callableReferenceExpression != null) {
return getCallableReferenceTypeInfo(expression, callableReferenceExpression, context, resolveArgumentsMode);
}
JetTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
if (recordedTypeInfo != null) {
return recordedTypeInfo;
}
ResolutionContext newContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(DEPENDENT);
return expressionTypingServices.getTypeInfo(expression, newContext);
}
@NotNull
public JetTypeInfo getCallableReferenceTypeInfo(
@NotNull JetExpression expression,
@NotNull JetCallableReferenceExpression callableReferenceExpression,
@NotNull CallResolutionContext<?> context,
@NotNull ResolveArgumentsMode resolveArgumentsMode
) {
if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
JetType type = getShapeTypeOfCallableReference(callableReferenceExpression, context, true);
return TypeInfoFactoryPackage.createTypeInfo(type);
}
return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
}
@Nullable
public JetType getShapeTypeOfCallableReference(
@NotNull JetCallableReferenceExpression callableReferenceExpression,
@NotNull CallResolutionContext<?> context,
boolean expectedTypeIsUnknown
) {
JetType receiverType =
CallableReferencesPackage.resolveCallableReferenceReceiverType(callableReferenceExpression, context, typeResolver);
OverloadResolutionResults<CallableDescriptor> overloadResolutionResults =
CallableReferencesPackage.resolvePossiblyAmbiguousCallableReference(
callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
callResolver);
return CallableReferencesPackage.getResolvedCallableReferenceShapeType(
callableReferenceExpression, overloadResolutionResults, context, expectedTypeIsUnknown,
reflectionTypes, builtIns);
}
@NotNull
public JetTypeInfo getFunctionLiteralTypeInfo(
@NotNull JetExpression expression,
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedT
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
@@ -194,7 +194,7 @@ public class CallCompleter(
context: BasicCallResolutionContext,
results: OverloadResolutionResultsImpl<D>
) {
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return
if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return
val getArgumentMapping: (ValueArgument) -> ArgumentMapping
val getDataFlowInfoForArgument: (ValueArgument) -> DataFlowInfo
@@ -247,10 +247,15 @@ public class CallCompleter(
// While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once),
// but they should be analyzed when the expected type is known (during the call completion).
if (ArgumentTypeResolver.isFunctionLiteralArgument(expression, context)) {
argumentTypeResolver.getFunctionLiteralTypeInfo(
expression, ArgumentTypeResolver.getFunctionLiteralArgument(expression, context),
context, RESOLVE_FUNCTION_ARGUMENTS)
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(expression, context)?.let { functionLiteralArgument ->
argumentTypeResolver.getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
}
// While the expected type is not known, (possibly overloaded) callable references can have placeholder types
// (to avoid exponential search for overloaded higher-order functions).
// They should be analyzed now.
ArgumentTypeResolver.getCallableReferenceExpressionIfAny(expression, context)?.let { callableReferenceArgument ->
argumentTypeResolver.getCallableReferenceTypeInfo(expression, callableReferenceArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
}
DataFlowUtils.checkType(updatedType, deparenthesized, context)
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
@@ -78,7 +78,7 @@ public class CallExpressionResolver {
@Nullable
public ResolvedCall<FunctionDescriptor> getResolvedCallForFunction(
@NotNull Call call, @NotNull JetExpression callExpression,
@NotNull ResolutionContext context, @NotNull CheckValueArgumentsMode checkArguments,
@NotNull ResolutionContext context, @NotNull CheckArgumentTypesMode checkArguments,
@NotNull boolean[] result
) {
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
@@ -101,7 +101,7 @@ public class CallExpressionResolver {
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
context.replaceTraceAndCache(temporaryForVariable),
call, CheckValueArgumentsMode.ENABLED);
call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
// if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
@@ -154,7 +154,7 @@ public class CallExpressionResolver {
context, "trace to resolve as function", nameExpression);
ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result);
call, nameExpression, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
if (result[0]) {
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
temporaryForFunction.commit();
@@ -198,7 +198,7 @@ public class CallExpressionResolver {
call, callExpression,
// It's possible start of a call so we should reset safe call chain
context.replaceTraceAndCache(temporaryForFunction).replaceInsideCallChain(false),
CheckValueArgumentsMode.ENABLED, result);
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
if (result[0]) {
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
temporaryForFunction.commit();
@@ -164,7 +164,7 @@ public class CallResolver {
@NotNull JetReferenceExpression functionReference,
@NotNull Name name
) {
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED);
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
return computeTasksAndResolveCall(
callResolutionContext, name, functionReference,
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
@@ -263,7 +263,7 @@ public class CallResolver {
) {
return resolveFunctionCall(
BasicCallResolutionContext.create(
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
additionalCheckerProvider.getCallChecker(), additionalCheckerProvider.getSymbolUsageValidator(),
additionalCheckerProvider.getTypeChecker(), isAnnotationContext)
);
@@ -344,7 +344,7 @@ public class CallResolver {
trace, scope,
CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
NO_EXPECTED_TYPE,
dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
callChecker, additionalCheckerProvider.getSymbolUsageValidator(), additionalCheckerProvider.getTypeChecker(), false);
if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
@@ -430,7 +430,7 @@ public class CallResolver {
@Override
public OverloadResolutionResults<FunctionDescriptor> invoke() {
BasicCallResolutionContext basicCallResolutionContext =
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, dataFlowInfoForArguments);
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
@@ -484,7 +484,7 @@ public class CallResolver {
CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
results.getResultingCall(), context, tracing);
genericCandidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
genericCandidateResolver.completeTypeInferenceDependentOnFunctionArgumentsForCall(candidateContext);
}
private static <F extends CallableDescriptor> void cacheResults(
@@ -515,7 +515,7 @@ public class CallResolver {
@NotNull CallTransformer<D, F> callTransformer,
@NotNull TracingStrategy tracing
) {
if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
}
Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.callResolverUtil
import com.google.common.collect.Lists
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
@@ -33,6 +34,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
import java.util.*
public enum class ResolveArgumentsMode {
RESOLVE_FUNCTION_ARGUMENTS,
@@ -41,30 +44,34 @@ public enum class ResolveArgumentsMode {
public fun hasUnknownFunctionParameter(type: JetType): Boolean {
assert(KotlinBuiltIns.isFunctionOrExtensionFunctionType(type))
val arguments = type.getArguments()
// last argument is return type of function type
val functionParameters = arguments.subList(0, arguments.size() - 1)
return functionParameters.any {
assert(ReflectionTypes.isCallableType(type), "type is not a function or property")
return getParameterArgumentsOfCallableType(type).any {
TypeUtils.containsSpecialType(it.getType(), DONT_CARE) || ErrorUtils.containsUninferredParameter(it.getType())
}
}
public fun hasUnknownReturnType(type: JetType): Boolean {
assert(KotlinBuiltIns.isFunctionOrExtensionFunctionType(type))
val returnTypeFromFunctionType = KotlinBuiltIns.getReturnTypeFromFunctionType(type)
return ErrorUtils.containsErrorType(returnTypeFromFunctionType)
assert(ReflectionTypes.isCallableType(type), "type is not a function or property")
return ErrorUtils.containsErrorType(getReturnTypeForCallable(type))
}
public fun replaceReturnTypeByUnknown(type: JetType): JetType {
assert(KotlinBuiltIns.isFunctionOrExtensionFunctionType(type))
val arguments = type.getArguments()
assert(ReflectionTypes.isCallableType(type), "type is not a function or property")
val newArguments = Lists.newArrayList<TypeProjection>()
newArguments.addAll(arguments.subList(0, arguments.size() - 1))
newArguments.addAll(getParameterArgumentsOfCallableType(type))
newArguments.add(TypeProjectionImpl(Variance.INVARIANT, DONT_CARE))
return JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isMarkedNullable(), newArguments, type.getMemberScope())
return replaceTypeArguments(type, newArguments)
}
private fun replaceTypeArguments(type: JetType, newArguments: List<TypeProjection>) =
JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isMarkedNullable(), newArguments, type.getMemberScope())
private fun getParameterArgumentsOfCallableType(type: JetType) =
type.getArguments().dropLast(1)
private fun getReturnTypeForCallable(type: JetType) =
type.getArguments().last().getType()
private fun CallableDescriptor.hasReturnTypeDependentOnUninferredParams(constraintSystem: ConstraintSystem): Boolean {
val returnType = getReturnType() ?: return false
@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.resolve.calls
import com.google.common.collect.Lists
import com.google.common.collect.Sets
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
import org.jetbrains.kotlin.diagnostics.Errors.SUPER_CANT_BE_EXTENSION_RECEIVER
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor
import org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS
@@ -60,11 +62,14 @@ import java.util.ArrayList
public class CandidateResolver(
private val argumentTypeResolver: ArgumentTypeResolver,
private val genericCandidateResolver: GenericCandidateResolver
private val genericCandidateResolver: GenericCandidateResolver,
private val reflectionTypes: ReflectionTypes
){
public fun <D : CallableDescriptor, F : D> performResolutionForCandidateCall(context: CallCandidateResolutionContext<D>,
task: ResolutionTask<D, F>): Unit = with(context) {
public fun <D : CallableDescriptor, F : D> performResolutionForCandidateCall(
context: CallCandidateResolutionContext<D>,
task: ResolutionTask<D, F>
): Unit = with(context) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
if (ErrorUtils.isError(candidateDescriptor)) {
@@ -78,7 +83,13 @@ public class CandidateResolver(
}
checkVisibility()
mapArguments(task)
when (task.checkArguments) {
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
mapArguments()
CheckArgumentTypesMode.CHECK_CALLABLE_TYPE ->
checkExpectedCallableType()
}
checkReceiverTypeError()
checkExtensionReceiver()
@@ -143,15 +154,27 @@ public class CandidateResolver(
}
}
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.mapArguments(task: ResolutionTask<D, F>) = check {
if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
call, tracing, candidateCall, Sets.newLinkedHashSet<ValueArgument>())
if (!argumentMappingStatus.isSuccess()) {
candidateCall.addStatus(OTHER_ERROR)
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.mapArguments()
= check {
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
call, tracing, candidateCall, Sets.newLinkedHashSet<ValueArgument>())
if (!argumentMappingStatus.isSuccess()) {
candidateCall.addStatus(OTHER_ERROR)
}
}
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.checkExpectedCallableType()
= check {
if (!noExpectedType(expectedType)) {
val candidate = candidateCall.getCandidateDescriptor()
val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, this, reflectionTypes);
if (candidateReflectionType != null) {
if (!JetTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) {
candidateCall.addStatus(OTHER_ERROR)
}
}
}
}
}
}
private fun CallCandidateResolutionContext<*>.checkVisibility() = checkAndReport {
val receiverValue = ExpressionTypingUtils.normalizeReceiverValueForVisibility(candidateCall.getDispatchReceiver(),
@@ -19,9 +19,7 @@ package org.jetbrains.kotlin.resolve.calls
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetPsiUtil
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getLastElementDeparenthesized
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.*
@@ -39,6 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
@@ -197,7 +196,7 @@ class GenericCandidateResolver(
return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes)
}
public fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionLiteralsForCall(
public fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionArgumentsForCall(
context: CallCandidateResolutionContext<D>
) {
val resolvedCall = context.candidateCall
@@ -210,30 +209,35 @@ class GenericCandidateResolver(
val valueParameterDescriptor = entry.getKey()
for (valueArgument in resolvedValueArgument.getArguments()) {
addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context)
valueArgument.getArgumentExpression()?.let { argumentExpression ->
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(argumentExpression, context)?.let { functionLiteral ->
addConstraintForFunctionLiteral(functionLiteral, valueArgument, valueParameterDescriptor, constraintSystem, context)
}
ArgumentTypeResolver.getCallableReferenceExpressionIfAny(argumentExpression, context)?.let { callableReference ->
addConstraintForCallableReference(callableReference, valueArgument, valueParameterDescriptor, constraintSystem, context)
}
}
}
}
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor())
}
private fun <D : CallableDescriptor> addConstraintForFunctionLiteral(
functionLiteral: JetFunction,
valueArgument: ValueArgument,
valueParameterDescriptor: ValueParameterDescriptor,
constraintSystem: ConstraintSystem,
context: CallCandidateResolutionContext<D>
) {
val argumentExpression = valueArgument.getArgumentExpression() ?: return
if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression, context)) return
val functionLiteral = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression, context)
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
var expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false)
}
if (expectedType == null || !KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)
|| hasUnknownFunctionParameter(expectedType)) {
if (expectedType == null || !KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType) ||
hasUnknownFunctionParameter(expectedType)) {
return
}
val dataFlowInfoForArguments = context.candidateCall.getDataFlowInfoForArguments()
@@ -267,6 +271,56 @@ class GenericCandidateResolver(
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, position)
}
private fun <D : CallableDescriptor> addConstraintForCallableReference(
callableReference: JetCallableReferenceExpression,
valueArgument: ValueArgument,
valueParameterDescriptor: ValueParameterDescriptor,
constraintSystem: ConstraintSystem,
context: CallCandidateResolutionContext<D>
) {
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
val expectedType = getExpectedTypeForCallableReference(callableReference, constraintSystem, context, effectiveExpectedType)
?: return
val resolvedType = getResolvedTypeForCallableReference(callableReference, context, expectedType, valueArgument)
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex())
constraintSystem.addSubtypeConstraint(resolvedType, effectiveExpectedType, position)
}
private fun <D : CallableDescriptor> getExpectedTypeForCallableReference(
callableReference: JetCallableReferenceExpression,
constraintSystem: ConstraintSystem,
context: CallCandidateResolutionContext<D>,
effectiveExpectedType: JetType
): JetType? {
val substitutedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
if (substitutedType != null && !TypeUtils.isDontCarePlaceholder(substitutedType))
return substitutedType
val shapeType = argumentTypeResolver.getShapeTypeOfCallableReference(callableReference, context, false)
if (shapeType != null && KotlinBuiltIns.isFunctionOrExtensionFunctionType(shapeType) && !hasUnknownFunctionParameter(shapeType))
return shapeType
return null
}
private fun <D : CallableDescriptor> getResolvedTypeForCallableReference(
callableReference: JetCallableReferenceExpression,
context: CallCandidateResolutionContext<D>,
expectedType: JetType,
valueArgument: ValueArgument
): JetType? {
val dataFlowInfoForArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(valueArgument)
val expectedTypeWithoutReturnType = if (!hasUnknownReturnType(expectedType)) replaceReturnTypeByUnknown(expectedType) else expectedType
val newContext = context
.replaceExpectedType(expectedTypeWithoutReturnType)
.replaceDataFlowInfo(dataFlowInfoForArgument)
.replaceContextDependency(INDEPENDENT)
val argumentExpression = valueArgument.getArgumentExpression()!!
val type = argumentTypeResolver.getCallableReferenceTypeInfo(
argumentExpression, callableReference, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
return type
}
}
fun getResolutionResultsCachedData(expression: JetExpression?, context: ResolutionContext<*>): ResolutionResultsCache.CachedData? {
@@ -37,7 +37,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ContextDependency contextDependency,
@NotNull CheckValueArgumentsMode checkArguments,
@NotNull CheckArgumentTypesMode checkArguments,
@NotNull ResolutionResultsCache resolutionResultsCache,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
@NotNull CallChecker callChecker,
@@ -60,7 +60,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ContextDependency contextDependency,
@NotNull CheckValueArgumentsMode checkArguments,
@NotNull CheckArgumentTypesMode checkArguments,
@NotNull CallChecker callChecker,
@NotNull SymbolUsageValidator symbolUsageValidator,
@NotNull AdditionalTypeChecker additionalTypeChecker,
@@ -73,7 +73,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull
public static BasicCallResolutionContext create(
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckValueArgumentsMode checkArguments,
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckArgumentTypesMode checkArguments,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
) {
return new BasicCallResolutionContext(
@@ -85,7 +85,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
@NotNull
public static BasicCallResolutionContext create(
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckValueArgumentsMode checkArguments
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckArgumentTypesMode checkArguments
) {
return create(context, call, checkArguments, null);
}
@@ -52,7 +52,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ContextDependency contextDependency,
@NotNull CheckValueArgumentsMode checkArguments,
@NotNull CheckArgumentTypesMode checkArguments,
@NotNull ResolutionResultsCache resolutionResultsCache,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
@NotNull CallChecker callChecker,
@@ -34,7 +34,7 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
@NotNull
public final Call call;
@NotNull
public final CheckValueArgumentsMode checkArguments;
public final CheckArgumentTypesMode checkArguments;
@NotNull
public final MutableDataFlowInfoForArguments dataFlowInfoForArguments;
@@ -45,7 +45,7 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ContextDependency contextDependency,
@NotNull CheckValueArgumentsMode checkArguments,
@NotNull CheckArgumentTypesMode checkArguments,
@NotNull ResolutionResultsCache resolutionResultsCache,
@SuppressWarnings("NullableProblems")
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
@@ -65,7 +65,7 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
if (dataFlowInfoForArguments != null) {
this.dataFlowInfoForArguments = dataFlowInfoForArguments;
}
else if (checkArguments == CheckValueArgumentsMode.ENABLED) {
else if (checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
this.dataFlowInfoForArguments = new DataFlowInfoForArgumentsImpl(call);
}
else {
@@ -16,7 +16,13 @@
package org.jetbrains.kotlin.resolve.calls.context;
public enum CheckValueArgumentsMode {
ENABLED,
DISABLED
public enum CheckArgumentTypesMode {
/**
* Check value argument types for particular call.
*/
CHECK_VALUE_ARGUMENTS,
/**
* Match callable reference type against expected (callable) type.
*/
CHECK_CALLABLE_TYPE
}
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.resolve.OverrideResolver;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionTask;
@@ -101,7 +101,7 @@ public class ResolutionResultsHandler {
boolean allCandidatesIncomplete = allIncomplete(results.getResultingCalls());
// This check is needed for the following case:
// x.foo(unresolved) -- if there are multiple foo's, we'd report an ambiguity, and it does not make sense here
if (task.checkArguments == CheckValueArgumentsMode.DISABLED ||
if (task.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ||
!CallUtilPackage.hasUnresolvedArguments(task.call, task)) {
if (allCandidatesIncomplete) {
task.tracing.cannotCompleteResolve(task.trace, results.getResultingCalls());
@@ -53,7 +53,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
@NotNull JetType expectedType,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull ContextDependency contextDependency,
@NotNull CheckValueArgumentsMode checkArguments,
@NotNull CheckArgumentTypesMode checkArguments,
@NotNull ResolutionResultsCache resolutionResultsCache,
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
@NotNull CallChecker callChecker,
@@ -30,17 +30,15 @@ import org.jetbrains.kotlin.JetNodeTypes;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl;
@@ -57,17 +55,13 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperPackage;
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
import org.jetbrains.kotlin.utils.ThrowingList;
import java.util.Collection;
import java.util.Collections;
@@ -78,12 +72,10 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.lexer.JetTokens.AS_KEYWORD;
import static org.jetbrains.kotlin.lexer.JetTokens.AS_SAFE;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getStaticNestedClassesScope;
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
import static org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue;
import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
import static org.jetbrains.kotlin.resolve.source.SourcePackage.toSourceElement;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
@@ -498,7 +490,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
trace.record(RESOLVED_CALL, call, resolvedCall);
trace.record(CALL, expression, call);
BasicCallResolutionContext resolutionContext = BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.DISABLED);
BasicCallResolutionContext resolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE);
context.callChecker.check(resolvedCall, resolutionContext);
context.symbolUsageValidator.validateCall(descriptor, trace, expression);
}
@@ -676,166 +668,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
) {
JetSimpleNameExpression reference = expression.getCallableReference();
boolean[] result = new boolean[1];
CallableDescriptor descriptor = resolveCallableReferenceTarget(
lhsType, context.replaceContextDependency(INDEPENDENT), expression, result);
if (!result[0]) {
boolean[] resolved = new boolean[1];
CallableDescriptor descriptor = CallableReferencesPackage.resolveCallableReferenceTarget(
expression, lhsType, context, resolved, components.callResolver);
if (!resolved[0]) {
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
}
if (descriptor == null) return null;
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter();
if (extensionReceiver != null && dispatchReceiver != null && descriptor instanceof CallableMemberDescriptor) {
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, (CallableMemberDescriptor) descriptor));
return null;
}
JetType receiverType = extensionReceiver != null ? extensionReceiver.getType() :
dispatchReceiver != null ? dispatchReceiver.getType() :
null;
if (descriptor instanceof FunctionDescriptor) {
return createFunctionReferenceType(expression, context, (FunctionDescriptor) descriptor, receiverType);
}
else if (descriptor instanceof PropertyDescriptor) {
return createPropertyReferenceType(expression, context, (PropertyDescriptor) descriptor, receiverType);
}
else if (descriptor instanceof VariableDescriptor) {
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
return null;
}
throw new UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: " + descriptor);
}
@Nullable
private JetType createFunctionReferenceType(
@NotNull JetCallableReferenceExpression expression,
@NotNull ExpressionTypingContext context,
@NotNull FunctionDescriptor descriptor,
@Nullable JetType receiverType
) {
//noinspection ConstantConditions
JetType type = components.reflectionTypes.getKFunctionType(
Annotations.EMPTY,
receiverType,
getValueParametersTypes(descriptor.getValueParameters()),
descriptor.getReturnType()
);
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
context.scope.getContainingDeclaration(),
Annotations.EMPTY,
CallableMemberDescriptor.Kind.DECLARATION,
toSourceElement(expression)
);
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
context.trace.record(FUNCTION, expression, functionDescriptor);
return type;
}
@Nullable
private JetType createPropertyReferenceType(
@NotNull JetCallableReferenceExpression expression,
@NotNull ExpressionTypingContext context,
@NotNull PropertyDescriptor descriptor,
@Nullable JetType receiverType
) {
JetType type = components.reflectionTypes.getKPropertyType(
Annotations.EMPTY, receiverType, descriptor.getType(), descriptor.isVar()
);
LocalVariableDescriptor localVariable =
new LocalVariableDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY, Name.special("<anonymous>"),
type, /* mutable = */ false, toSourceElement(expression));
context.trace.record(VARIABLE, expression, localVariable);
return type;
}
@Nullable
private CallableDescriptor resolveCallableReferenceTarget(
@Nullable JetType lhsType,
@NotNull ExpressionTypingContext context,
@NotNull JetCallableReferenceExpression expression,
@NotNull boolean[] result
) {
JetSimpleNameExpression reference = expression.getCallableReference();
if (lhsType == null) {
return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result);
}
ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor();
if (!(classifier instanceof ClassDescriptor)) {
context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression));
return null;
}
JetScope staticScope = ((ClassDescriptor) classifier).getStaticScope();
TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
context, "trace to resolve callable reference in static scope", reference);
CallableDescriptor possibleStatic = resolveCallableNotCheckingArguments(
reference, NO_RECEIVER, context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
if (result[0]) {
temporaryForStatic.commit();
return possibleStatic;
}
JetScope staticNestedClasses = getStaticNestedClassesScope((ClassDescriptor) classifier);
TemporaryTraceAndCache temporaryForNested = TemporaryTraceAndCache.create(
context, "trace to resolve callable reference in static nested classes scope", reference);
CallableDescriptor possibleNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
context.replaceTraceAndCache(temporaryForNested).replaceScope(staticNestedClasses), result);
if (result[0]) {
temporaryForNested.commit();
return possibleNestedClassConstructor;
}
ReceiverValue receiver = new TransientReceiver(lhsType);
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
context, "trace to resolve callable reference with receiver", reference);
CallableDescriptor descriptor = resolveCallableNotCheckingArguments(
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
if (result[0]) {
temporaryWithReceiver.commit();
return descriptor;
}
return null;
}
@Nullable
private CallableDescriptor resolveCallableNotCheckingArguments(
@NotNull JetSimpleNameExpression reference,
@NotNull ReceiverValue receiver,
@NotNull ExpressionTypingContext context,
@NotNull boolean[] result
) {
Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
TemporaryTraceAndCache temporaryTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as function",
reference);
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(
context.replaceTraceAndCache(temporaryTrace).replaceExpectedType(NO_EXPECTED_TYPE), call, CheckValueArgumentsMode.DISABLED);
OverloadResolutionResults<CallableDescriptor> results =
components.callResolver.resolveCallForMember(reference, callResolutionContext);
if (!results.isNothing()) {
temporaryTrace.commit();
result[0] = true;
ResolvedCall<CallableDescriptor> callable =
OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency);
if (callable != null) {
return callable.getResultingDescriptor();
}
}
return null;
return CallableReferencesPackage.createReflectionTypeForResolvedCallableReference(expression, descriptor, context, components.reflectionTypes);
}
@Override
@@ -21,14 +21,18 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalyzerPackage;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.resolve.scopes.WritableScope;
@@ -301,4 +305,5 @@ public class ExpressionTypingServices {
}
return result;
}
}
@@ -0,0 +1,22 @@
import kotlin.test.assertEquals
fun foo(): String = "foo1"
fun foo(i: Int): String = "foo2"
val f1: () -> String = ::foo
val f2: (Int) -> String = ::foo
fun foo1() {}
fun foo2(i: Int) {}
fun bar(f: () -> Unit): String = "bar1"
fun bar(f: (Int) -> Unit): String = "bar2"
fun box(): String {
assertEquals("foo1", f1())
assertEquals("foo2", f2(0))
assertEquals("bar1", bar(::foo1))
assertEquals("bar2", bar(::foo2))
return "OK"
}
@@ -0,0 +1,19 @@
import kotlin.reflect.*
import kotlin.test.assertEquals
class A {
val x = 1
fun x(): String = "OK"
}
val f1: KProperty1<A, Int> = A::x
val f2: (A) -> String = A::x
fun box(): String {
val a = A()
assertEquals(1, f1.get(a))
assertEquals("OK", f2(a))
return "OK"
}
@@ -5,5 +5,5 @@ fun foo(<!UNUSED_PARAMETER!>x<!>: Any, y: Int) = y
fun main() {
::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>
val fooRef: (Int, Any) -> Unit = ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>
val fooRef: (Int, Any) -> Unit = ::<!NONE_APPLICABLE!>foo<!>
}
@@ -0,0 +1,22 @@
// FILE: A.kt
open class A<T>(val x: T)
// FILE: AFactory.kt
abstract class AFactory {
abstract fun create(): A<Int>?
}
// FILE: Util.kt
inline fun <reified T> createWith(x: T, f: (T) -> A<T>?)
= f(x)
// FILE: B.kt
class B(x: Int) : A<Int>(x) {
companion object : AFactory() {
override fun create(): A<Int>? = createWith(0, ::B)
}
}
@@ -0,0 +1,35 @@
package
kotlin.inline() internal fun </*0*/ reified T> createWith(/*0*/ x: T, /*1*/ f: (T) -> A<T>?): A<T>?
internal open class A</*0*/ T> {
public constructor A</*0*/ T>(/*0*/ x: T)
internal final val x: T
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
internal abstract class AFactory {
public constructor AFactory()
internal abstract fun create(): A<kotlin.Int>?
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
internal final class B : A<kotlin.Int> {
public constructor B(/*0*/ x: kotlin.Int)
internal final override /*1*/ /*fake_override*/ val x: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion : AFactory {
private constructor Companion()
internal open override /*1*/ fun create(): A<kotlin.Int>?
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,8 @@
import kotlin.reflect.KProperty1
fun <T, R> getProperty(x: T, property: KProperty1<T, R>): R =
property.get(x)
class Person(val name: String)
val name1 = getProperty(Person("John Smith"), Person::name)
@@ -0,0 +1,12 @@
package
internal val name1: kotlin.String
internal fun </*0*/ T, /*1*/ R> getProperty(/*0*/ x: T, /*1*/ property: kotlin.reflect.KProperty1<T, R>): R
internal final class Person {
public constructor Person(/*0*/ name: kotlin.String)
internal final val name: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,19 @@
// FILE: Customer.java
public class Customer {
private String name;
public Customer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// FILE: test.kt
val customerName = Customer::name
@@ -0,0 +1,13 @@
package
internal val customerName: kotlin.reflect.KMutableProperty1<Customer, kotlin.String!>
public open class Customer {
public constructor Customer(/*0*/ name: kotlin.String!)
private final var name: kotlin.String!
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun getName(): kotlin.String!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open fun setName(/*0*/ name: kotlin.String!): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
fun fn(f: () -> Unit) {}
fun test() {
fn(::foo)
}
@@ -0,0 +1,6 @@
package
internal fun fn(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
internal fun test(): kotlin.Unit
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <T> ofType(x: T): T = x
fun foo() {}
fun foo(s: String) {}
val x1 = ofType<() -> Unit>(::foo)
val x2 = ofType<(String) -> Unit>(::foo)
val x3 = ofType<(Int) -> Unit>(::<!NONE_APPLICABLE!>foo<!>)
@@ -0,0 +1,8 @@
package
internal val x1: () -> kotlin.Unit
internal val x2: (kotlin.String) -> kotlin.Unit
internal val x3: (kotlin.Int) -> kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
internal fun </*0*/ T> ofType(/*0*/ x: T): T
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
val x1 = ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>
val x2: () -> Unit = ::foo
val x3: (String) -> Unit = ::foo
val x4: (Int) -> Unit = ::<!NONE_APPLICABLE!>foo<!>
@@ -0,0 +1,8 @@
package
internal val x1: [ERROR : Type for ::foo]
internal val x2: () -> kotlin.Unit
internal val x3: (kotlin.String) -> kotlin.Unit
internal val x4: (kotlin.Int) -> kotlin.Unit
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Klass {
constructor(a: Int) {}
constructor(a: String) {}
}
fun user(f: (Int) -> Klass) {}
fun fn() {
user(::Klass)
}
@@ -0,0 +1,12 @@
package
internal fun fn(): kotlin.Unit
internal fun user(/*0*/ f: (kotlin.Int) -> Klass): kotlin.Unit
internal final class Klass {
public constructor Klass(/*0*/ a: kotlin.Int)
public constructor Klass(/*0*/ a: kotlin.String)
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.*
class A {
val x = 1
fun x() {}
}
fun f1(): KProperty<Int> = A::x // ok, property
fun f2(): (A) -> Unit = A::x // ok, function
@@ -0,0 +1,13 @@
package
internal fun f1(): kotlin.reflect.KProperty<kotlin.Int>
internal fun f2(): (A) -> kotlin.Unit
internal final class A {
public constructor A()
internal final val x: kotlin.Int = 1
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
internal final fun x(): kotlin.Unit
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo() {}
fun foo(s: String) {}
fun bar(f: () -> Unit) = 1
fun bar(f: (String) -> Unit) = 2
val x1 = ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> as () -> Unit
val x2 = bar(::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> as (String) -> Unit)
@@ -0,0 +1,8 @@
package
internal val x1: () -> kotlin.Unit
internal val x2: kotlin.Int
internal fun bar(/*0*/ f: () -> kotlin.Unit): kotlin.Int
internal fun bar(/*0*/ f: (kotlin.String) -> kotlin.Unit): kotlin.Int
internal fun foo(): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
@@ -0,0 +1,28 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
import kotlin.reflect.*
fun <T> ofType(x: T): T = x
class A {
val foo: Int = 0
fun foo() {}
fun bar() {}
val bar: Int = 0
}
fun A.foo(): String = "A"
val x0 = A::foo // function A::foo wins by default
val userOfX0 = x0(A())
val x1 = ofType<(A) -> Unit>(A::foo)
val x2 = ofType<KProperty1<A, Int>>(A::foo)
val x3: KProperty1<A, Int> = A::foo
val x4: (A) -> String = A::foo
val y0 = A::bar
val y1 = ofType<(A) -> Unit>(A::bar)
val y2 = ofType<KProperty1<A, Int>>(A::bar)
val y3: KProperty1<A, Int> = A::bar
@@ -0,0 +1,25 @@
package
internal val userOfX0: kotlin.Unit
internal val x0: kotlin.reflect.KFunction1<A, kotlin.Unit>
internal val x1: (A) -> kotlin.Unit
internal val x2: kotlin.reflect.KProperty1<A, kotlin.Int>
internal val x3: kotlin.reflect.KProperty1<A, kotlin.Int>
internal val x4: (A) -> kotlin.String
internal val y0: kotlin.reflect.KFunction1<A, kotlin.Unit>
internal val y1: (A) -> kotlin.Unit
internal val y2: kotlin.reflect.KProperty1<A, kotlin.Int>
internal val y3: kotlin.reflect.KProperty1<A, kotlin.Int>
internal fun </*0*/ T> ofType(/*0*/ x: T): T
internal fun A.foo(): kotlin.String
internal final class A {
public constructor A()
internal final val bar: kotlin.Int = 0
internal final val foo: kotlin.Int = 0
internal final fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
internal final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <T, R> apply(x: T, f: (T) -> R): R = f(x)
fun foo(i: Int) {}
fun foo(s: String) {}
val x1 = apply(1, ::foo)
val x2 = apply("hello", ::foo)
val x3 = apply(true, ::<!NONE_APPLICABLE!>foo<!>)
@@ -0,0 +1,8 @@
package
internal val x1: kotlin.Unit
internal val x2: kotlin.Unit
internal val x3: [ERROR : Type for apply(true, ::foo)]
internal fun </*0*/ T, /*1*/ R> apply(/*0*/ x: T, /*1*/ f: (T) -> R): R
internal fun foo(/*0*/ i: kotlin.Int): kotlin.Unit
internal fun foo(/*0*/ s: kotlin.String): kotlin.Unit
@@ -0,0 +1,26 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER,-CONFLICTING_JVM_DECLARATIONS
fun foo(i: Int) = "$i"
fun foo(s: String) = s
fun bar(s: String) = s
fun qux(i: Int, j: Int, k: Int): Int = i + j + k
fun qux(a: String, b: String, c: String, d: String) {}
fun fn1(x: Int, f1: (Int) -> String, f2: (String) -> String) = f2(f1(x))
fun fn2(f1: (Int) -> String, f2: (String) -> String ) = f2(f1(0))
fun fn2(f1: (Int) -> Int, f2: (Int) -> String ) = f2(f1(0))
fun fn2(f1: (String) -> String, f2: (String) -> String ) = f2(f1(""))
fun fn3(i: Int, f: (Int, Int, Int) -> Int): Int = f(i, i, i)
val x1 = fn1(1, ::foo, ::foo)
val x2 = fn1(1, ::foo, ::bar)
val x3 = fn2(::bar, ::foo)
val x4 = fn2(::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>, ::bar)
val x5 = fn2(::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>, ::<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>)
val x6 = fn3(1, ::qux)
@@ -0,0 +1,18 @@
package
internal val x1: kotlin.String
internal val x2: kotlin.String
internal val x3: kotlin.String
internal val x4: [ERROR : Type for fn2(::foo, ::bar)]
internal val x5: [ERROR : Type for fn2(::foo, ::foo)]
internal val x6: kotlin.Int
internal fun bar(/*0*/ s: kotlin.String): kotlin.String
internal fun fn1(/*0*/ x: kotlin.Int, /*1*/ f1: (kotlin.Int) -> kotlin.String, /*2*/ f2: (kotlin.String) -> kotlin.String): kotlin.String
internal fun fn2(/*0*/ f1: (kotlin.Int) -> kotlin.Int, /*1*/ f2: (kotlin.Int) -> kotlin.String): kotlin.String
internal fun fn2(/*0*/ f1: (kotlin.Int) -> kotlin.String, /*1*/ f2: (kotlin.String) -> kotlin.String): kotlin.String
internal fun fn2(/*0*/ f1: (kotlin.String) -> kotlin.String, /*1*/ f2: (kotlin.String) -> kotlin.String): kotlin.String
internal fun fn3(/*0*/ i: kotlin.Int, /*1*/ f: (kotlin.Int, kotlin.Int, kotlin.Int) -> kotlin.Int): kotlin.Int
internal fun foo(/*0*/ i: kotlin.Int): kotlin.String
internal fun foo(/*0*/ s: kotlin.String): kotlin.String
internal fun qux(/*0*/ i: kotlin.Int, /*1*/ j: kotlin.Int, /*2*/ k: kotlin.Int): kotlin.Int
internal fun qux(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String, /*2*/ c: kotlin.String, /*3*/ d: kotlin.String): kotlin.Unit
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo(vararg ii: Int) {}
fun foo(vararg ss: String) {}
fun foo(i: Int) {}
val fn1: (Int) -> Unit = ::foo
val fn2: (IntArray) -> Unit = ::foo
val fn3: (Int, Int) -> Unit = <!TYPE_MISMATCH!>::foo<!>
val fn4: (Array<String>) -> Unit = ::foo
@@ -0,0 +1,9 @@
package
internal val fn1: (kotlin.Int) -> kotlin.Unit
internal val fn2: (kotlin.IntArray) -> kotlin.Unit
internal val fn3: (kotlin.Int, kotlin.Int) -> kotlin.Unit
internal val fn4: (kotlin.Array<kotlin.String>) -> kotlin.Unit
internal fun foo(/*0*/ vararg ss: kotlin.String /*kotlin.Array<out kotlin.String>*/): kotlin.Unit
internal fun foo(/*0*/ i: kotlin.Int): kotlin.Unit
internal fun foo(/*0*/ vararg ii: kotlin.Int /*kotlin.IntArray*/): kotlin.Unit
@@ -1352,6 +1352,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("constructorFromCompanion.kt")
public void testConstructorFromCompanion() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/function/constructorFromCompanion.kt");
doTest(fileName);
}
@TestMetadata("constructorFromExtension.kt")
public void testConstructorFromExtension() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/function/constructorFromExtension.kt");
@@ -1721,18 +1727,99 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("returnTypeDependentOnGenericProperty.kt")
public void testReturnTypeDependentOnGenericProperty() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/property/returnTypeDependentOnGenericProperty.kt");
doTest(fileName);
}
@TestMetadata("samePriorityForFunctionsAndProperties.kt")
public void testSamePriorityForFunctionsAndProperties() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/property/samePriorityForFunctionsAndProperties.kt");
doTest(fileName);
}
@TestMetadata("syntheticProperties.kt")
public void testSyntheticProperties() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/property/syntheticProperties.kt");
doTest(fileName);
}
@TestMetadata("topLevelFromTopLevel.kt")
public void testTopLevelFromTopLevel() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/property/topLevelFromTopLevel.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/callableReference/resolve")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Resolve extends AbstractJetDiagnosticsTest {
public void testAllFilesPresentInResolve() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/callableReference/resolve"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("byArgType.kt")
public void testByArgType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/byArgType.kt");
doTest(fileName);
}
@TestMetadata("byGenericArgType.kt")
public void testByGenericArgType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/byGenericArgType.kt");
doTest(fileName);
}
@TestMetadata("byValType.kt")
public void testByValType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/byValType.kt");
doTest(fileName);
}
@TestMetadata("constructor.kt")
public void testConstructor() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/constructor.kt");
doTest(fileName);
}
@TestMetadata("valVsFun.kt")
public void testValVsFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt");
doTest(fileName);
}
@TestMetadata("withAs.kt")
public void testWithAs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/withAs.kt");
doTest(fileName);
}
@TestMetadata("withExtFun.kt")
public void testWithExtFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/withExtFun.kt");
doTest(fileName);
}
@TestMetadata("withGenericFun.kt")
public void testWithGenericFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/withGenericFun.kt");
doTest(fileName);
}
@TestMetadata("withPlaceholderTypes.kt")
public void testWithPlaceholderTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/withPlaceholderTypes.kt");
doTest(fileName);
}
@TestMetadata("withVararg.kt")
public void testWithVararg() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/resolve/withVararg.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/cast")
@@ -561,6 +561,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("overloadedFun.kt")
public void testOverloadedFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/callableReference/function/overloadedFun.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("overloadedFunVsVal.kt")
public void testOverloadedFunVsVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/callableReference/function/overloadedFunVsVal.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("privateClassMember.kt")
public void testPrivateClassMember() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/callableReference/function/privateClassMember.kt");
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
import java.util.ArrayList
val KOTLIN_REFLECT_FQ_NAME = FqName("kotlin.reflect")
@@ -112,5 +113,33 @@ public class ReflectionTypes(private val module: ModuleDescriptor) {
val containingPackage = DescriptorUtils.getParentOfType(descriptor, javaClass<PackageFragmentDescriptor>())
return containingPackage != null && containingPackage.fqName == KOTLIN_REFLECT_FQ_NAME
}
private val PROPERTY_CLASS_NAMES = hashSetOf(
"KProperty", "KMutableProperty",
"KProperty0", "KMutableProperty0",
"KProperty1", "KMutableProperty1",
"KProperty2", "KMutableProperty2"
)
public fun isCallableType(type: JetType): Boolean =
KotlinBuiltIns.isFunctionOrExtensionFunctionType(type) ||
isPropertyType(type)
public fun isPropertyType(type: JetType): Boolean =
isExactPropertyType(type) ||
type.getConstructor().getSupertypes().any { isPropertyType(it) }
public fun isExactPropertyType(type: JetType): Boolean {
val descriptor = type.getConstructor().getDeclarationDescriptor()
if (descriptor is ClassDescriptor) {
val fqName = DescriptorUtils.getFqName(descriptor)
val parentName = fqName.parent().asString()
if (parentName != KOTLIN_REFLECT_FQ_NAME.asString())
return false
val shortName = fqName.shortName().asString()
return PROPERTY_CLASS_NAMES.contains(shortName)
}
return false
}
}
}
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CompositeChecker
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
@@ -165,7 +165,7 @@ public class ShadowedDeclarationsFilter(
val dataFlowInfo = bindingContext.getDataFlowInfo(calleeExpression)
val context = BasicCallResolutionContext.create(bindingTrace, resolutionScope, newCall, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
CompositeChecker(listOf()), SymbolUsageValidator.Empty, AdditionalTypeChecker.Composite(listOf()), false)
val callResolver = createContainerForMacros(project, moduleDescriptor).callResolver
val results = if (isFunction) callResolver.resolveFunctionCall(context) else callResolver.resolveSimpleProperty(context)
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.noErrorsInValueArguments
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CompositeChecker
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
@@ -155,7 +155,7 @@ class ExpectedInfos(
val dataFlowInfo = bindingContext.getDataFlowInfo(calleeExpression)
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for completion")
val context = BasicCallResolutionContext.create(bindingTrace, resolutionScope, truncatedCall, expectedType, dataFlowInfo,
ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
CompositeChecker(listOf()), SymbolUsageValidator.Empty, AdditionalTypeChecker.Composite(listOf()), false)
val callResolutionContext = context.replaceCollectAllCandidates(true)
val callResolver = createContainerForMacros(