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:
Generated
+2
@@ -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>
|
||||
|
||||
+276
@@ -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)
|
||||
}
|
||||
+72
-10
@@ -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)
|
||||
|
||||
+5
-5
@@ -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(),
|
||||
|
||||
+64
-10
@@ -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? {
|
||||
|
||||
+4
-4
@@ -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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
+9
-3
@@ -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
|
||||
}
|
||||
+2
-2
@@ -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,
|
||||
|
||||
+8
-167
@@ -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
|
||||
|
||||
+5
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
@@ -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"
|
||||
}
|
||||
+19
@@ -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"
|
||||
}
|
||||
Vendored
+1
-1
@@ -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<!>
|
||||
}
|
||||
|
||||
+22
@@ -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)
|
||||
}
|
||||
}
|
||||
Vendored
+35
@@ -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
|
||||
}
|
||||
}
|
||||
+8
@@ -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)
|
||||
+12
@@ -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
|
||||
}
|
||||
+19
@@ -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
|
||||
+13
@@ -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
|
||||
+10
@@ -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<!>)
|
||||
+8
@@ -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)
|
||||
}
|
||||
+12
@@ -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
|
||||
}
|
||||
+10
@@ -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<!>)
|
||||
+8
@@ -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
|
||||
+26
@@ -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)
|
||||
+18
@@ -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")
|
||||
|
||||
+12
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user