[FE 1.0] Don't fail candidates which were marked with compatibility resolve previously

^KT-52431 Fixed
^KT-52393 Fixed
This commit is contained in:
Victor Petukhov
2022-05-20 14:09:22 +02:00
committed by teamcity
parent 73d676d9de
commit 02a430875f
17 changed files with 198 additions and 23 deletions
@@ -892,18 +892,23 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() {
for (variableWithConstraints in getSystem().getBuilder().currentStorage().notFixedTypeVariables.values) {
val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness()
// TODO: consider reporting errors on bounded type variables by incompatible types but with other lower constraints
if (
variableWithConstraints.constraints.none { it.kind.isLower() }
&& upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()
) {
val isInferredEmptyIntersectionForbidden =
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
when {
// TODO: consider reporting errors on bounded type variables by incompatible types but with other lower constraints
upperTypes.size <= 1 || variableWithConstraints.constraints.any { it.kind.isLower() } ->
continue
wasPreviouslyDiscriminated(upperTypes) -> {
markCandidateForCompatibilityResolve(needToReportWarning = false)
continue
}
upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty() -> {
val isInferredEmptyIntersectionForbidden =
callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
val errorFactory = if (isInferredEmptyIntersectionForbidden || wasPreviouslyDiscriminated(upperTypes))
::InferredEmptyIntersectionError
else ::InferredEmptyIntersectionWarning
addError(errorFactory(upperTypes, variableWithConstraints.typeVariable))
val errorFactory = if (isInferredEmptyIntersectionForbidden)
::InferredEmptyIntersectionError
else ::InferredEmptyIntersectionWarning
addError(errorFactory(upperTypes, variableWithConstraints.typeVariable))
}
}
}
}
@@ -160,12 +160,15 @@ open class MutableResolvedCallAtom(
override fun toString(): String = "$atom, candidate = $candidateDescriptor"
}
fun ResolutionCandidate.markCandidateForCompatibilityResolve() {
fun ResolutionCandidate.markCandidateForCompatibilityResolve(needToReportWarning: Boolean = true) {
if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return
addDiagnostic(LowerPriorityToPreserveCompatibility.asDiagnostic())
addDiagnostic(LowerPriorityToPreserveCompatibility(needToReportWarning).asDiagnostic())
}
fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(diagnostics: SmartList<KotlinCallDiagnostic>) {
fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(
diagnostics: SmartList<KotlinCallDiagnostic>,
needToReportWarning: Boolean = true,
) {
if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return
diagnostics.add(LowerPriorityToPreserveCompatibility.asDiagnostic())
diagnostics.add(LowerPriorityToPreserveCompatibility(needToReportWarning).asDiagnostic())
}
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
import org.jetbrains.kotlin.resolve.calls.model.constraintSystemError
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.descriptorUtil.HIDES_MEMBERS_NAME_LIST
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
@@ -437,13 +440,21 @@ class TowerResolver {
}
if (firstGroupWithResolved == null) return null
if (compatibilityCandidate != null && compatibilityGroup !== firstGroupWithResolved) {
if (compatibilityCandidate != null
&& compatibilityGroup !== firstGroupWithResolved
&& needToReportCompatibilityWarning(compatibilityCandidate)
) {
firstGroupWithResolved.forEach { it.addCompatibilityWarning(compatibilityCandidate) }
}
return firstGroupWithResolved.filter(::isSuccessfulCandidate)
}
private fun needToReportCompatibilityWarning(candidate: C) = candidate is ResolutionCandidate &&
candidate.diagnostics.any {
(it.constraintSystemError as? LowerPriorityToPreserveCompatibility)?.needToReportWarning == true
}
private fun isSuccessfulCandidate(candidate: C): Boolean {
return candidate.resultingApplicability == CandidateApplicability.RESOLVED
|| candidate.resultingApplicability == CandidateApplicability.RESOLVED_WITH_ERROR