[NI] Continue resolution after unstable smart cast on receiver

The old inference cosideres candidates with unstable smartcast on
receiver unsuccessful, therefore another one may be selected.
KT-36264
This commit is contained in:
Pavel Kirpichenkov
2020-02-11 17:53:11 +03:00
parent 4997c9535c
commit 15d744c3da
12 changed files with 126 additions and 10 deletions
@@ -64,7 +64,7 @@ private fun checkExpressionArgument(
): KotlinCallDiagnostic? {
if (unstableType != null) {
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, actualExpectedType, position)) {
return UnstableSmartCast(expressionArgument, unstableType)
return UnstableSmartCast(expressionArgument, unstableType, isReceiver)
}
}
@@ -112,7 +112,7 @@ private fun checkExpressionArgument(
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
if (unstableType != null && csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
diagnosticsHolder.addDiagnostic(UnstableSmartCast(expressionArgument, unstableType))
diagnosticsHolder.addDiagnostic(UnstableSmartCast(expressionArgument, unstableType, isReceiver))
} else if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
diagnosticsHolder.addDiagnostic(UnsafeCallError(expressionArgument))
} else {
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
@@ -138,11 +139,23 @@ class SmartCastDiagnostic(
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
class UnstableSmartCast(
class UnstableSmartCast private constructor(
val argument: ExpressionKotlinCallArgument,
val targetType: UnwrappedType
) : KotlinCallDiagnostic(RESOLVED_WITH_ERROR) {
val targetType: UnwrappedType,
applicability: ResolutionCandidateApplicability,
) : KotlinCallDiagnostic(applicability) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
companion object {
operator fun invoke(
argument: ExpressionKotlinCallArgument,
targetType: UnwrappedType,
isReceiver: Boolean = false,
): UnstableSmartCast {
val applicability = if (isReceiver) MAY_THROW_RUNTIME_ERROR else RESOLVED_WITH_ERROR
return UnstableSmartCast(argument, targetType, applicability)
}
}
}
class UnsafeCallError(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagnostic(MAY_THROW_RUNTIME_ERROR) {