[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 -> { NewConstraintError::class.java -> {
val constraintError = diagnostic as NewConstraintError val constraintError = diagnostic as NewConstraintError
val position = constraintError.position.from val position = constraintError.position.from
(position as? ArgumentConstraintPosition)?.let { val argument = (position as? ArgumentConstraintPosition)?.argument
val expression = it.argument.psiExpression ?: return ?: (position as? ReceiverConstraintPosition)?.argument
argument?.let {
val expression = it.psiExpression ?: return
if (reportConstantTypeMismatch(constraintError, expression)) return if (reportConstantTypeMismatch(constraintError, expression)) return
trace.report(Errors.TYPE_MISMATCH.on(expression, constraintError.upperType, constraintError.lowerType)) 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) { fun ResolutionCandidateApplicability.toResolutionStatus(): ResolutionStatus = when (this) {
ResolutionCandidateApplicability.RESOLVED, ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY -> ResolutionStatus.SUCCESS ResolutionCandidateApplicability.RESOLVED, ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY -> ResolutionStatus.SUCCESS
ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER -> ResolutionStatus.RECEIVER_TYPE_ERROR
else -> ResolutionStatus.OTHER_ERROR else -> ResolutionStatus.OTHER_ERROR
} }
} }
@@ -194,7 +194,10 @@ class PSICallResolver(
} }
1 -> { 1 -> {
val singleCandidate = result.single() 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) return SingleOverloadResolutionResult(resolvedCall)
} }
else -> { else -> {
@@ -225,12 +228,7 @@ class PSICallResolver(
private fun Collection<ResolvedKotlinCall>.areAllCompletedAndInapplicable() = private fun Collection<ResolvedKotlinCall>.areAllCompletedAndInapplicable() =
all { all {
val applicability = when (it) { val applicability = it.currentStatus.resultingApplicability
is ResolvedKotlinCall.CompletedResolvedKotlinCall ->
it.completedCall.resolutionStatus.resultingApplicability
is ResolvedKotlinCall.OnlyResolvedKotlinCall ->
it.candidate.status.resultingApplicability
}
applicability == ResolutionCandidateApplicability.INAPPLICABLE || applicability == ResolutionCandidateApplicability.HIDDEN 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.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible 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.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.inference.model.TypeVariableForLambdaReturnType
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
@@ -203,7 +205,7 @@ internal fun checkExpressionArgument(
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.stableType, expectedType) val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.stableType, expectedType)
fun unstableSmartCastOrSubtypeError( fun unstableSmartCastOrSubtypeError(
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ArgumentConstraintPosition unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ConstraintPosition
): KotlinCallDiagnostic? { ): KotlinCallDiagnostic? {
if (unstableType != null) { if (unstableType != null) {
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) { if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
@@ -215,7 +217,7 @@ internal fun checkExpressionArgument(
} }
val expectedNullableType = expectedType.makeNullableAsSpecified(true) val expectedNullableType = expectedType.makeNullableAsSpecified(true)
val position = ArgumentConstraintPosition(expressionArgument) val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
if (expressionArgument.isSafeCall) { if (expressionArgument.isSafeCall) {
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) { if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
return unstableSmartCastOrSubtypeError(expressionArgument.unstableType, expectedNullableType, position)?.let { return it } return unstableSmartCastOrSubtypeError(expressionArgument.unstableType, expectedNullableType, position)?.let { return it }
@@ -37,6 +37,11 @@ class DeclaredUpperBoundConstraintPosition(val typeParameterDescriptor: TypePara
class ArgumentConstraintPosition(val argument: KotlinCallArgument) : ConstraintPosition() { class ArgumentConstraintPosition(val argument: KotlinCallArgument) : ConstraintPosition() {
override fun toString() = "Argument $argument" override fun toString() = "Argument $argument"
} }
class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintPosition() {
override fun toString() = "Receiver $argument"
}
class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() { class FixVariableConstraintPosition(val variable: NewTypeVariable) : ConstraintPosition() {
override fun toString() = "Fix variable $variable" override fun toString() = "Fix variable $variable"
} }
@@ -57,8 +62,11 @@ class IncorporationConstraintPosition(val from: ConstraintPosition, val initialC
object SimpleConstraintSystemConstraintPosition : ConstraintPosition() object SimpleConstraintSystemConstraintPosition : ConstraintPosition()
class NewConstraintError(val lowerType: UnwrappedType, val upperType: UnwrappedType, val position: IncorporationConstraintPosition): class NewConstraintError(val lowerType: UnwrappedType, val upperType: UnwrappedType, val position: IncorporationConstraintPosition) :
KotlinCallDiagnostic(ResolutionCandidateApplicability.INAPPLICABLE) { KotlinCallDiagnostic(
if (position.from is ReceiverConstraintPosition) ResolutionCandidateApplicability.INAPPLICABLE_WRONG_RECEIVER
else ResolutionCandidateApplicability.INAPPLICABLE
) {
override fun report(reporter: DiagnosticReporter) = reporter.constraintError(this) 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.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor 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.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateStatus
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
sealed class ResolvedKotlinCall { sealed class ResolvedKotlinCall {
abstract val currentStatus: ResolutionCandidateStatus
class CompletedResolvedKotlinCall( class CompletedResolvedKotlinCall(
val completedCall: CompletedKotlinCall, val completedCall: CompletedKotlinCall,
val allInnerCalls: Collection<CompletedKotlinCall>, val allInnerCalls: Collection<CompletedKotlinCall>,
val lambdaArguments: List<ResolvedLambdaArgument> 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 { sealed class CompletedKotlinCall {