[NI] Support INAPPLICABLE_WRONG_RECEIVER candidate applicability

It is important for provideDelegate resolution, because if scope has
provideDelegate with wrong receiver we shouldn't resolve to it and
report any errors.
This commit is contained in:
Stanislav Erokhin
2017-06-08 19:16:33 +03:00
committed by Mikhail Zarechenskiy
parent e4b73fcdbd
commit 5f2cc75718
6 changed files with 32 additions and 16 deletions
@@ -151,8 +151,10 @@ class DiagnosticReporterByTrackingStrategy(
NewConstraintError::class.java -> {
val constraintError = diagnostic as NewConstraintError
val position = constraintError.position.from
(position as? ArgumentConstraintPosition)?.let {
val expression = it.argument.psiExpression ?: return
val argument = (position as? ArgumentConstraintPosition)?.argument
?: (position as? ReceiverConstraintPosition)?.argument
argument?.let {
val expression = it.psiExpression ?: return
if (reportConstantTypeMismatch(constraintError, expression)) return
trace.report(Errors.TYPE_MISMATCH.on(expression, constraintError.upperType, constraintError.lowerType))
}
@@ -479,6 +479,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
fun ResolutionCandidateApplicability.toResolutionStatus(): ResolutionStatus = when (this) {
ResolutionCandidateApplicability.RESOLVED, ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY -> ResolutionStatus.SUCCESS
ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER -> ResolutionStatus.RECEIVER_TYPE_ERROR
else -> ResolutionStatus.OTHER_ERROR
}
}
@@ -194,7 +194,10 @@ class PSICallResolver(
}
1 -> {
val singleCandidate = result.single()
val resolvedCall = kotlinToResolvedCallTransformer.transformAndReport<D>(singleCandidate, context, trace)
val reportToTrace = singleCandidate.currentStatus.resultingApplicability != ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
val resolvedCall = kotlinToResolvedCallTransformer.transformAndReport<D>(singleCandidate, context, trace.takeIf { reportToTrace })
return SingleOverloadResolutionResult(resolvedCall)
}
else -> {
@@ -225,12 +228,7 @@ class PSICallResolver(
private fun Collection<ResolvedKotlinCall>.areAllCompletedAndInapplicable() =
all {
val applicability = when (it) {
is ResolvedKotlinCall.CompletedResolvedKotlinCall ->
it.completedCall.resolutionStatus.resultingApplicability
is ResolvedKotlinCall.OnlyResolvedKotlinCall ->
it.candidate.status.resultingApplicability
}
val applicability = it.currentStatus.resultingApplicability
applicability == ResolutionCandidateApplicability.INAPPLICABLE || applicability == ResolutionCandidateApplicability.HIDDEN
}
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.resolve.calls.components.CreateDescriptorWithFreshTy
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.ReceiverConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
@@ -203,7 +205,7 @@ internal fun checkExpressionArgument(
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.stableType, expectedType)
fun unstableSmartCastOrSubtypeError(
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ArgumentConstraintPosition
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ConstraintPosition
): KotlinCallDiagnostic? {
if (unstableType != null) {
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
@@ -215,7 +217,7 @@ internal fun checkExpressionArgument(
}
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
val position = ArgumentConstraintPosition(expressionArgument)
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
if (expressionArgument.isSafeCall) {
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
return unstableSmartCastOrSubtypeError(expressionArgument.unstableType, expectedNullableType, position)?.let { return it }
@@ -37,6 +37,11 @@ class DeclaredUpperBoundConstraintPosition(val typeParameterDescriptor: TypePara
class ArgumentConstraintPosition(val argument: KotlinCallArgument) : ConstraintPosition() {
override fun toString() = "Argument $argument"
}
class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintPosition() {
override fun toString() = "Receiver $argument"
}
class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() {
override fun toString() = "Fix variable $variable"
}
@@ -57,8 +62,11 @@ class IncorporationConstraintPosition(val from: ConstraintPosition, val initialC
object SimpleConstraintSystemConstraintPosition : ConstraintPosition()
class NewConstraintError(val lowerType: UnwrappedType, val upperType: UnwrappedType, val position: IncorporationConstraintPosition):
KotlinCallDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE) {
class NewConstraintError(val lowerType: UnwrappedType, val upperType: UnwrappedType, val position: IncorporationConstraintPosition) :
KotlinCallDiagnostic(
if (position.from is ReceiverConstraintPosition) ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
else ResolutionCandidateApplicability.INAPPLICABLE
) {
override fun report(reporter: DiagnosticReporter) = reporter.constraintError(this)
}
@@ -18,20 +18,25 @@ package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.UnwrappedType
sealed class ResolvedKotlinCall {
abstract val currentStatus: ResolutionCandidateStatus
class CompletedResolvedKotlinCall(
val completedCall: CompletedKotlinCall,
val allInnerCalls: Collection<CompletedKotlinCall>,
val lambdaArguments: List<ResolvedLambdaArgument>
): ResolvedKotlinCall()
): ResolvedKotlinCall() {
override val currentStatus get() = completedCall.resolutionStatus
}
class OnlyResolvedKotlinCall(val candidate: KotlinResolutionCandidate) : ResolvedKotlinCall()
class OnlyResolvedKotlinCall(val candidate: KotlinResolutionCandidate) : ResolvedKotlinCall() {
override val currentStatus get() = candidate.status
}
}
sealed class CompletedKotlinCall {