[NI] Fix reporting of overload resolution ambiguity

This commit is contained in:
Dmitriy Novozhilov
2019-04-19 14:29:05 +03:00
parent f9cc3d9be3
commit bfb13803d5
8 changed files with 24 additions and 20 deletions
@@ -20,14 +20,12 @@ import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver import org.jetbrains.kotlin.resolve.calls.KotlinCallResolver
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isBinaryRemOperator import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isBinaryRemOperator
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation import org.jetbrains.kotlin.resolve.calls.callUtil.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.buildResultingSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
@@ -232,7 +230,7 @@ class PSICallResolver(
} }
diagnostics.firstIsInstanceOrNull<ManyCandidatesCallDiagnostic>()?.let { diagnostics.firstIsInstanceOrNull<ManyCandidatesCallDiagnostic>()?.let {
return transformManyCandidatesAndRecordTrace(it, tracingStrategy, trace) return transformManyCandidatesAndRecordTrace(it, tracingStrategy, trace, context)
} }
if (getResultApplicability(diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) { if (getResultApplicability(diagnostics) == ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER) {
@@ -250,7 +248,8 @@ class PSICallResolver(
private fun <D : CallableDescriptor> transformManyCandidatesAndRecordTrace( private fun <D : CallableDescriptor> transformManyCandidatesAndRecordTrace(
diagnostic: ManyCandidatesCallDiagnostic, diagnostic: ManyCandidatesCallDiagnostic,
tracingStrategy: TracingStrategy, tracingStrategy: TracingStrategy,
trace: BindingTrace trace: BindingTrace,
context: BasicCallResolutionContext
): ManyCandidates<D> { ): ManyCandidates<D> {
val resolvedCalls = diagnostic.candidates.map { val resolvedCalls = diagnostic.candidates.map {
kotlinToResolvedCallTransformer.onlyTransform<D>( kotlinToResolvedCallTransformer.onlyTransform<D>(
@@ -267,10 +266,10 @@ class PSICallResolver(
} }
} else { } else {
tracingStrategy.recordAmbiguity(trace, resolvedCalls) tracingStrategy.recordAmbiguity(trace, resolvedCalls)
if (resolvedCalls.first().status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) { if (!context.call.hasUnresolvedArguments(context)) {
tracingStrategy.cannotCompleteResolve(trace, resolvedCalls) if (resolvedCalls.allIncomplete) {
} else { tracingStrategy.cannotCompleteResolve(trace, resolvedCalls)
if (!resolvedCalls.all { it.isNewNotCompleted() }) { } else {
tracingStrategy.ambiguity(trace, resolvedCalls) tracingStrategy.ambiguity(trace, resolvedCalls)
} }
} }
@@ -278,6 +277,8 @@ class PSICallResolver(
return ManyCandidates(resolvedCalls) return ManyCandidates(resolvedCalls)
} }
private val List<ResolvedCall<*>>.allIncomplete: Boolean get() = all { it.status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE }
private fun ResolvedCall<*>.recordEffects(trace: BindingTrace) { private fun ResolvedCall<*>.recordEffects(trace: BindingTrace) {
val moduleDescriptor = DescriptorUtils.getContainingModule(this.resultingDescriptor?.containingDeclaration ?: return) val moduleDescriptor = DescriptorUtils.getContainingModule(this.resultingDescriptor?.containingDeclaration ?: return)
recordLambdasInvocations(trace, moduleDescriptor) recordLambdasInvocations(trace, moduleDescriptor)
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.CallTransformer import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.isError
@@ -78,8 +79,10 @@ fun <C : ResolutionContext<C>> Call.hasUnresolvedArguments(context: ResolutionCo
return arguments.any(fun(argument: KtExpression?): Boolean { return arguments.any(fun(argument: KtExpression?): Boolean {
if (argument == null || ArgumentTypeResolver.isFunctionLiteralOrCallableReference(argument, context)) return false if (argument == null || ArgumentTypeResolver.isFunctionLiteralOrCallableReference(argument, context)) return false
val resolvedCall = argument.getResolvedCall(context.trace.bindingContext) as MutableResolvedCall<*>? when (val resolvedCall = argument.getResolvedCall(context.trace.bindingContext)) {
if (resolvedCall != null && !resolvedCall.hasInferredReturnType()) return false is MutableResolvedCall<*> -> if (!resolvedCall.hasInferredReturnType()) return false
is NewResolvedCallImpl<*> -> if (resolvedCall.resultingDescriptor.returnType?.isError == true) return false
}
val expressionType = context.trace.bindingContext.getType(argument) val expressionType = context.trace.bindingContext.getType(argument)
return expressionType == null || expressionType.isError return expressionType == null || expressionType.isError
@@ -13,7 +13,7 @@ fun test1() {
<!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!UNUSED_ANONYMOUS_PARAMETER!>s<!>: String<!>-> "" <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!UNUSED_ANONYMOUS_PARAMETER!>s<!>: String<!>-> ""
}<!> }<!>
foo0 <!NI;TYPE_MISMATCH!>{ foo0 <!NI;TYPE_MISMATCH!>{
<!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!CANNOT_INFER_PARAMETER_TYPE, UNUSED_ANONYMOUS_PARAMETER!>x<!>, <!NI;CANNOT_INFER_PARAMETER_TYPE, OI;CANNOT_INFER_PARAMETER_TYPE, UNUSED_ANONYMOUS_PARAMETER!>y<!><!> -> "" <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!CANNOT_INFER_PARAMETER_TYPE, UNUSED_ANONYMOUS_PARAMETER!>x<!>, <!CANNOT_INFER_PARAMETER_TYPE, UNUSED_ANONYMOUS_PARAMETER!>y<!><!> -> ""
}<!> }<!>
foo1 { foo1 {
@@ -8,6 +8,6 @@ fun bar(i: Int) {}
fun bar(s: String) {} fun bar(s: String) {}
fun test() { fun test() {
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(<!UNRESOLVED_REFERENCE!>rrr<!>, 1) foo(<!UNRESOLVED_REFERENCE!>rrr<!>, 1)
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>bar<!>(<!UNRESOLVED_REFERENCE!>rrr<!>) bar(<!UNRESOLVED_REFERENCE!>rrr<!>)
} }
@@ -2,7 +2,7 @@
fun foo() { fun foo() {
fun bar1() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar1<!>()<!> fun bar1() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar1<!>()<!>
fun bar2() = 1 <!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar2<!>()<!> fun bar2() = 1 + <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar2<!>()<!>
fun <!NI;IMPLICIT_NOTHING_RETURN_TYPE!>bar3<!>() = <!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>id<!>(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!>()<!>) fun <!NI;IMPLICIT_NOTHING_RETURN_TYPE!>bar3<!>() = <!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>id<!>(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!>()<!>)
} }
@@ -4,7 +4,7 @@ fun import() {
} }
fun composite() { fun composite() {
val <!UNUSED_VARIABLE!>s<!> = 13<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>+<!><!SYNTAX!>~<!><!DEBUG_INFO_MISSING_UNRESOLVED!>/<!>12 val <!UNUSED_VARIABLE!>s<!> = 13+<!SYNTAX!>~<!><!DEBUG_INFO_MISSING_UNRESOLVED!>/<!>12
} }
fun html() { fun html() {
+1 -1
View File
@@ -11,7 +11,7 @@ fun foo() : Int {
<!USELESS_IS_CHECK!>is Any<!> -> <!UNUSED_EXPRESSION!>1<!> <!USELESS_IS_CHECK!>is Any<!> -> <!UNUSED_EXPRESSION!>1<!>
<!INCOMPATIBLE_TYPES!>s<!> -> <!UNUSED_EXPRESSION!>1<!> <!INCOMPATIBLE_TYPES!>s<!> -> <!UNUSED_EXPRESSION!>1<!>
1 -> <!UNUSED_EXPRESSION!>1<!> 1 -> <!UNUSED_EXPRESSION!>1<!>
1 <!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!> 1 + <!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!>
in 1..<!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!> in 1..<!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!>
!in 1..<!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!> !in 1..<!UNRESOLVED_REFERENCE!>a<!> -> <!UNUSED_EXPRESSION!>1<!>
else -> <!UNUSED_EXPRESSION!>1<!> else -> <!UNUSED_EXPRESSION!>1<!>
@@ -4,12 +4,12 @@ fun test(mc: MutableCollection<out CharSequence>) {
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>mc<!>) mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>mc<!>)
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>arrayListOf<CharSequence>()<!>) mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>arrayListOf<CharSequence>()<!>)
mc.addAll(<!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>arrayListOf<!>()) mc.addAll(<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>arrayListOf<!>())
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf("")<!>) mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf("")<!>)
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<String>("")<!>) mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<String>("")<!>)
mc.addAll(<!NI;TYPE_MISMATCH, TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<CharSequence>("")<!>) mc.addAll(<!NI;TYPE_MISMATCH, TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<CharSequence>("")<!>)
mc.addAll(<!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>emptyList<!>()) mc.addAll(<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>emptyList<!>())
mc.addAll(emptyList<Nothing>()) mc.addAll(emptyList<Nothing>())
} }