[NI] Split KotlinCallDiagnostics and inference errors to different hierarchies

This commit is contained in:
Dmitriy Novozhilov
2020-08-25 18:14:02 +03:00
parent fae21d4db3
commit 59b2cb6393
20 changed files with 102 additions and 83 deletions
@@ -1229,7 +1229,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
is ConeInapplicableCandidateError -> { is ConeInapplicableCandidateError -> {
describeVerbose(diagnostic.candidateSymbol) describeVerbose(diagnostic.candidateSymbol)
br br
diagnostic.diagnostics.forEach { callDiagnostic -> diagnostic.errors.forEach { callDiagnostic ->
when (callDiagnostic) { when (callDiagnostic) {
is NewConstraintError -> { is NewConstraintError -> {
ident() ident()
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
class ConeUnresolvedReferenceError(val name: Name? = null) : ConeDiagnostic() { class ConeUnresolvedReferenceError(val name: Name? = null) : ConeDiagnostic() {
override val reason: String get() = "Unresolved reference" + if (name != null) ": ${name.asString()}" else "" override val reason: String get() = "Unresolved reference" + if (name != null) ": ${name.asString()}" else ""
@@ -38,7 +38,7 @@ class ConeHiddenCandidateError(
class ConeInapplicableCandidateError( class ConeInapplicableCandidateError(
val applicability: CandidateApplicability, val applicability: CandidateApplicability,
val candidateSymbol: AbstractFirBasedSymbol<*>, val candidateSymbol: AbstractFirBasedSymbol<*>,
val diagnostics: List<KotlinCallDiagnostic> val errors: List<ConstraintSystemError>
) : ConeDiagnostic() { ) : ConeDiagnostic() {
constructor(applicability: CandidateApplicability, candidate: Candidate) : this( constructor(applicability: CandidateApplicability, candidate: Candidate) : this(
applicability, applicability,
@@ -69,15 +69,6 @@ class DiagnosticReporterByTrackingStrategy(
val reportOn = (diagnostic as NonApplicableCallForBuilderInferenceDiagnostic).kotlinCall val reportOn = (diagnostic as NonApplicableCallForBuilderInferenceDiagnostic).kotlinCall
trace.reportDiagnosticOnce(Errors.NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE.on(reportOn.psiKotlinCall.psiCall.callElement)) trace.reportDiagnosticOnce(Errors.NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE.on(reportOn.psiKotlinCall.psiCall.callElement))
} }
OnlyInputTypesDiagnostic::class.java -> {
val typeVariable = (diagnostic as OnlyInputTypesDiagnostic).typeVariable as? TypeVariableFromCallableDescriptor ?: return
psiKotlinCall.psiCall.calleeExpression?.let {
val factory = if (context.languageVersionSettings.supportsFeature(LanguageFeature.NonStrictOnlyInputTypesChecks))
TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING
else TYPE_INFERENCE_ONLY_INPUT_TYPES
trace.report(factory.on(it, typeVariable.originalTypeParameter))
}
}
CandidateChosenUsingOverloadResolutionByLambdaAnnotation::class.java -> { CandidateChosenUsingOverloadResolutionByLambdaAnnotation::class.java -> {
trace.report(CANDIDATE_CHOSEN_USING_OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION.on(psiKotlinCall.psiCall.callElement)) trace.report(CANDIDATE_CHOSEN_USING_OVERLOAD_RESOLUTION_BY_LAMBDA_ANNOTATION.on(psiKotlinCall.psiCall.callElement))
} }
@@ -340,10 +331,10 @@ class DiagnosticReporterByTrackingStrategy(
) )
} }
override fun constraintError(diagnostic: KotlinCallDiagnostic) { override fun constraintError(error: ConstraintSystemError) {
when (diagnostic.javaClass) { when (error.javaClass) {
NewConstraintError::class.java -> { NewConstraintError::class.java -> {
val constraintError = diagnostic as NewConstraintError val constraintError = error as NewConstraintError
val position = constraintError.position.from val position = constraintError.position.from
val argument = val argument =
when (position) { when (position) {
@@ -414,7 +405,8 @@ class DiagnosticReporterByTrackingStrategy(
(position as? FixVariableConstraintPositionImpl)?.let { (position as? FixVariableConstraintPositionImpl)?.let {
val morePreciseDiagnosticExists = allDiagnostics.any { other -> val morePreciseDiagnosticExists = allDiagnostics.any { other ->
other is NewConstraintError && other.position.from !is FixVariableConstraintPositionImpl val otherError = other.constraintSystemError ?: return@any false
otherError is NewConstraintError && otherError.position.from !is FixVariableConstraintPositionImpl
} }
if (morePreciseDiagnosticExists) return if (morePreciseDiagnosticExists) return
@@ -432,7 +424,7 @@ class DiagnosticReporterByTrackingStrategy(
} }
CapturedTypeFromSubtyping::class.java -> { CapturedTypeFromSubtyping::class.java -> {
val capturedError = diagnostic as CapturedTypeFromSubtyping val capturedError = error as CapturedTypeFromSubtyping
val position = capturedError.position val position = capturedError.position
val argumentPosition = val argumentPosition =
position.safeAs<ArgumentConstraintPositionImpl>() position.safeAs<ArgumentConstraintPositionImpl>()
@@ -449,11 +441,18 @@ class DiagnosticReporterByTrackingStrategy(
} }
} }
NotEnoughInformationForTypeParameter::class.java -> { NotEnoughInformationForTypeParameterImpl::class.java -> {
val error = diagnostic as NotEnoughInformationForTypeParameterImpl val error = error as NotEnoughInformationForTypeParameterImpl
if (allDiagnostics.any { if (allDiagnostics.any {
(it is ConstrainingTypeIsError && it.typeVariable == error.typeVariable) when (it) {
|| it is NewConstraintError || it is WrongCountOfTypeArguments is WrongCountOfTypeArguments -> true
is KotlinConstraintSystemDiagnostic -> {
val otherError = it.error
(otherError is ConstrainingTypeIsError && otherError.typeVariable == error.typeVariable)
|| otherError is NewConstraintError
}
else -> false
}
} }
) return ) return
@@ -473,6 +472,16 @@ class DiagnosticReporterByTrackingStrategy(
} }
trace.reportDiagnosticOnce(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(expression, typeVariableName)) trace.reportDiagnosticOnce(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(expression, typeVariableName))
} }
OnlyInputTypesDiagnostic::class.java -> {
val typeVariable = (error as OnlyInputTypesDiagnostic).typeVariable as? TypeVariableFromCallableDescriptor ?: return
psiKotlinCall.psiCall.calleeExpression?.let {
val factory = if (context.languageVersionSettings.supportsFeature(LanguageFeature.NonStrictOnlyInputTypesChecks))
TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING
else TYPE_INFERENCE_ONLY_INPUT_TYPES
trace.report(factory.on(it, typeVariable.originalTypeParameter))
}
}
} }
} }
@@ -60,7 +60,6 @@ class CoroutineInferenceSession(
// Simple calls are calls which might not have gone through type inference, but may contain unsubstituted postponed variables inside their types. // Simple calls are calls which might not have gone through type inference, but may contain unsubstituted postponed variables inside their types.
private val simpleCommonCalls = arrayListOf<KtExpression>() private val simpleCommonCalls = arrayListOf<KtExpression>()
private val diagnostics = arrayListOf<KotlinCallDiagnostic>()
private var hasInapplicableCall = false private var hasInapplicableCall = false
override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean { override fun shouldRunCompletion(candidate: KotlinResolutionCandidate): Boolean {
@@ -276,20 +275,16 @@ class CoroutineInferenceSession(
if (hasConstraints) effectivelyEmptyCommonSystem = false if (hasConstraints) effectivelyEmptyCommonSystem = false
} }
for (diagnostic in diagnostics) {
commonSystem.addError(diagnostic)
}
return commonSystem to effectivelyEmptyCommonSystem return commonSystem to effectivelyEmptyCommonSystem
} }
private fun reportDiagnostics(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, diagnostics: List<KotlinCallDiagnostic>) { private fun reportErrors(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, errors: List<ConstraintSystemError>) {
kotlinToResolvedCallTransformer.reportCallDiagnostic( kotlinToResolvedCallTransformer.reportCallDiagnostic(
completedCall.context, completedCall.context,
trace, trace,
completedCall.callResolutionResult.resultCallAtom, completedCall.callResolutionResult.resultCallAtom,
resolvedCall.resultingDescriptor, resolvedCall.resultingDescriptor,
diagnostics errors.asDiagnostics()
) )
} }
@@ -304,12 +299,12 @@ class CoroutineInferenceSession(
for (completedCall in commonCalls) { for (completedCall in commonCalls) {
updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult) updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult)
reportDiagnostics(completedCall, completedCall.resolvedCall, commonSystem.diagnostics) reportErrors(completedCall, completedCall.resolvedCall, commonSystem.diagnostics)
} }
for (callInfo in partiallyResolvedCallsInfo) { for (callInfo in partiallyResolvedCallsInfo) {
val resolvedCall = completeCall(callInfo, atomCompleter) ?: continue val resolvedCall = completeCall(callInfo, atomCompleter) ?: continue
reportDiagnostics(callInfo, resolvedCall, commonSystem.diagnostics) reportErrors(callInfo, resolvedCall, commonSystem.diagnostics)
} }
for (simpleCall in simpleCommonCalls) { for (simpleCall in simpleCommonCalls) {
@@ -904,10 +904,10 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
} }
diagnostics.forEach { diagnostics.forEach {
val position = when (it) { val position = when (val error = it.constraintSystemError) {
is NewConstraintError -> it.position.originalPosition() is NewConstraintError -> error.position.originalPosition()
is CapturedTypeFromSubtyping -> it.position.originalPosition() is CapturedTypeFromSubtyping -> error.position.originalPosition()
is ConstrainingTypeIsError -> it.position.originalPosition() is ConstrainingTypeIsError -> error.position.originalPosition()
else -> null else -> null
} as? ArgumentConstraintPositionImpl ?: return@forEach } as? ArgumentConstraintPositionImpl ?: return@forEach
@@ -170,7 +170,7 @@ abstract class ManyCandidatesResolver<D : CallableDescriptor>(
diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder, diagnosticsHolder: KotlinDiagnosticsHolder.SimpleHolder,
commonSystem: NewConstraintSystem commonSystem: NewConstraintSystem
): CallResolutionResult { ): CallResolutionResult {
val diagnostics = diagnosticsHolder.getDiagnostics() + callResolutionResult.diagnostics + commonSystem.diagnostics val diagnostics = diagnosticsHolder.getDiagnostics() + callResolutionResult.diagnostics + commonSystem.diagnostics.asDiagnostics()
return CompletedCallResolutionResult(callResolutionResult.resultCallAtom, diagnostics, commonSystem.asReadOnlyStorage()) return CompletedCallResolutionResult(callResolutionResult.resultCallAtom, diagnostics, commonSystem.asReadOnlyStorage())
} }
} }
@@ -281,7 +281,7 @@ class PSICallResolver(
): ManyCandidates<D> { ): ManyCandidates<D> {
val resolvedCalls = diagnostic.candidates.map { val resolvedCalls = diagnostic.candidates.map {
kotlinToResolvedCallTransformer.onlyTransform<D>( kotlinToResolvedCallTransformer.onlyTransform<D>(
it.resolvedCall, it.diagnosticsFromResolutionParts + it.getSystem().diagnostics it.resolvedCall, it.diagnosticsFromResolutionParts + it.getSystem().diagnostics.asDiagnostics()
) )
} }
@@ -236,7 +236,7 @@ class KotlinCallCompleter(
} }
} }
constraintSystem.diagnostics.forEach(diagnosticsHolder::addDiagnostic) constraintSystem.diagnostics.forEach(diagnosticsHolder::addError)
} }
private fun prepareCandidateForCompletion( private fun prepareCandidateForCompletion(
@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
interface NewConstraintSystem { interface NewConstraintSystem {
val hasContradiction: Boolean val hasContradiction: Boolean
val diagnostics: List<KotlinCallDiagnostic> val diagnostics: List<ConstraintSystemError>
fun getBuilder(): ConstraintSystemBuilder fun getBuilder(): ConstraintSystemBuilder
@@ -20,7 +20,6 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.* import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.*
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.*
@@ -43,7 +42,7 @@ class ConstraintInjector(
val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker>
fun addInitialConstraint(initialConstraint: InitialConstraint) fun addInitialConstraint(initialConstraint: InitialConstraint)
fun addError(error: KotlinCallDiagnostic) fun addError(error: ConstraintSystemError)
} }
fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) { fun addInitialSubtypeConstraint(c: Context, lowerType: KotlinTypeMarker, upperType: KotlinTypeMarker, position: ConstraintPosition) {
@@ -43,7 +43,7 @@ class KotlinConstraintSystemCompleter(
fun containsOnlyFixedOrPostponedVariables(type: KotlinTypeMarker): Boolean fun containsOnlyFixedOrPostponedVariables(type: KotlinTypeMarker): Boolean
// mutable operations // mutable operations
fun addError(error: KotlinCallDiagnostic) fun addError(error: ConstraintSystemError)
fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, atom: ResolvedAtom?) fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, atom: ResolvedAtom?)
@@ -16,8 +16,6 @@
package org.jetbrains.kotlin.resolve.calls.inference.model package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.resolve.calls.model.DiagnosticReporter
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.* import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.KotlinTypeMarker
@@ -89,31 +87,33 @@ object CoroutinePosition : ConstraintPosition() {
// TODO: should be used only in SimpleConstraintSystemImpl // TODO: should be used only in SimpleConstraintSystemImpl
object SimpleConstraintSystemConstraintPosition : ConstraintPosition() object SimpleConstraintSystemConstraintPosition : ConstraintPosition()
abstract class ConstraintSystemCallDiagnostic(applicability: ResolutionCandidateApplicability) : KotlinCallDiagnostic(applicability) { // ------------------------------------------------ Errors ------------------------------------------------
override fun report(reporter: DiagnosticReporter) = reporter.constraintError(this)
} sealed class ConstraintSystemError(val applicability: ResolutionCandidateApplicability)
class NewConstraintError( class NewConstraintError(
val lowerType: KotlinTypeMarker, val lowerType: KotlinTypeMarker,
val upperType: KotlinTypeMarker, val upperType: KotlinTypeMarker,
val position: IncorporationConstraintPosition val position: IncorporationConstraintPosition
) : ConstraintSystemCallDiagnostic(if (position.from is ReceiverConstraintPosition<*>) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE) ) : ConstraintSystemError(if (position.from is ReceiverConstraintPosition<*>) INAPPLICABLE_WRONG_RECEIVER else INAPPLICABLE)
class CapturedTypeFromSubtyping( class CapturedTypeFromSubtyping(
val typeVariable: TypeVariableMarker, val typeVariable: TypeVariableMarker,
val constraintType: KotlinTypeMarker, val constraintType: KotlinTypeMarker,
val position: ConstraintPosition val position: ConstraintPosition
) : ConstraintSystemCallDiagnostic(INAPPLICABLE) ) : ConstraintSystemError(INAPPLICABLE)
abstract class NotEnoughInformationForTypeParameter<T>( abstract class NotEnoughInformationForTypeParameter<T>(
val typeVariable: TypeVariableMarker, val typeVariable: TypeVariableMarker,
val resolvedAtom: T val resolvedAtom: T
) : ConstraintSystemCallDiagnostic(INAPPLICABLE) ) : ConstraintSystemError(INAPPLICABLE)
class ConstrainingTypeIsError( class ConstrainingTypeIsError(
val typeVariable: TypeVariableMarker, val typeVariable: TypeVariableMarker,
val constraintType: KotlinTypeMarker, val constraintType: KotlinTypeMarker,
val position: IncorporationConstraintPosition val position: IncorporationConstraintPosition
) : ConstraintSystemCallDiagnostic(INAPPLICABLE) ) : ConstraintSystemError(INAPPLICABLE)
object LowerPriorityToPreserveCompatibility : ConstraintSystemCallDiagnostic(RESOLVED_NEED_PRESERVE_COMPATIBILITY) class OnlyInputTypesDiagnostic(val typeVariable: TypeVariableMarker) : ConstraintSystemError(INAPPLICABLE)
object LowerPriorityToPreserveCompatibility : ConstraintSystemError(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
@@ -5,9 +5,11 @@
package org.jetbrains.kotlin.resolve.calls.inference.model package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
/** /**
* Every type variable can be in the following states: * Every type variable can be in the following states:
@@ -36,7 +38,7 @@ interface ConstraintStorage {
val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints> val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
val initialConstraints: List<InitialConstraint> val initialConstraints: List<InitialConstraint>
val maxTypeDepthFromInitialConstraints: Int val maxTypeDepthFromInitialConstraints: Int
val errors: List<KotlinCallDiagnostic> val errors: List<ConstraintSystemError>
val hasContradiction: Boolean val hasContradiction: Boolean
val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker> val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker>
val postponedTypeVariables: List<TypeVariableMarker> val postponedTypeVariables: List<TypeVariableMarker>
@@ -46,7 +48,7 @@ interface ConstraintStorage {
override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints> get() = emptyMap() override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints> get() = emptyMap()
override val initialConstraints: List<InitialConstraint> get() = emptyList() override val initialConstraints: List<InitialConstraint> get() = emptyList()
override val maxTypeDepthFromInitialConstraints: Int get() = 1 override val maxTypeDepthFromInitialConstraints: Int get() = 1
override val errors: List<KotlinCallDiagnostic> get() = emptyList() override val errors: List<ConstraintSystemError> get() = emptyList()
override val hasContradiction: Boolean get() = false override val hasContradiction: Boolean get() = false
override val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker> get() = emptyMap() override val fixedTypeVariables: Map<TypeConstructorMarker, KotlinTypeMarker> get() = emptyMap()
override val postponedTypeVariables: List<TypeVariableMarker> get() = emptyList() override val postponedTypeVariables: List<TypeVariableMarker> get() = emptyList()
@@ -139,4 +141,4 @@ fun checkConstraint(
ConstraintKind.LOWER -> typeChecker.isSubtypeOf(context, constraintType, resultType) ConstraintKind.LOWER -> typeChecker.isSubtypeOf(context, constraintType, resultType)
ConstraintKind.UPPER -> typeChecker.isSubtypeOf(context, resultType, constraintType) ConstraintKind.UPPER -> typeChecker.isSubtypeOf(context, resultType, constraintType)
} }
} }
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.resolve.calls.inference.model package org.jetbrains.kotlin.resolve.calls.inference.model
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.KotlinTypeMarker
@@ -191,8 +190,8 @@ internal class MutableConstraintStorage : ConstraintStorage {
override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap() override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap()
override val initialConstraints: MutableList<InitialConstraint> = SmartList() override val initialConstraints: MutableList<InitialConstraint> = SmartList()
override var maxTypeDepthFromInitialConstraints: Int = 1 override var maxTypeDepthFromInitialConstraints: Int = 1
override val errors: MutableList<KotlinCallDiagnostic> = SmartList() override val errors: MutableList<ConstraintSystemError> = SmartList()
override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess } override val hasContradiction: Boolean get() = errors.any { !it.applicability.isSuccess }
override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> = LinkedHashMap() override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> = LinkedHashMap()
override val postponedTypeVariables: MutableList<TypeVariableMarker> = SmartList() override val postponedTypeVariables: MutableList<TypeVariableMarker> = SmartList()
} }
@@ -11,8 +11,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjecto
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.model.OnlyInputTypesDiagnostic
import org.jetbrains.kotlin.resolve.calls.model.ResolvedAtom import org.jetbrains.kotlin.resolve.calls.model.ResolvedAtom
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
@@ -75,7 +73,7 @@ class NewConstraintSystemImpl(
} }
} }
override val diagnostics: List<KotlinCallDiagnostic> override val diagnostics: List<ConstraintSystemError>
get() = storage.errors get() = storage.errors
override fun getBuilder() = apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) } override fun getBuilder() = apply { checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) }
@@ -291,7 +289,7 @@ class NewConstraintSystemImpl(
} }
// ConstraintInjector.Context, KotlinConstraintSystemCompleter.Context // ConstraintInjector.Context, KotlinConstraintSystemCompleter.Context
override fun addError(error: KotlinCallDiagnostic) { override fun addError(error: ConstraintSystemError) {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION) checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
storage.errors.add(error) storage.errors.add(error)
} }
@@ -16,9 +16,8 @@
package org.jetbrains.kotlin.resolve.calls.model package org.jetbrains.kotlin.resolve.calls.model
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE
import org.jetbrains.kotlin.types.KotlinType
abstract class KotlinCallDiagnostic(val candidateApplicability: ResolutionCandidateApplicability) { abstract class KotlinCallDiagnostic(val candidateApplicability: ResolutionCandidateApplicability) {
abstract fun report(reporter: DiagnosticReporter) abstract fun report(reporter: DiagnosticReporter)
@@ -41,5 +40,5 @@ interface DiagnosticReporter {
fun onCallArgumentName(callArgument: KotlinCallArgument, diagnostic: KotlinCallDiagnostic) fun onCallArgumentName(callArgument: KotlinCallArgument, diagnostic: KotlinCallDiagnostic)
fun onCallArgumentSpread(callArgument: KotlinCallArgument, diagnostic: KotlinCallDiagnostic) fun onCallArgumentSpread(callArgument: KotlinCallArgument, diagnostic: KotlinCallDiagnostic)
fun constraintError(diagnostic: KotlinCallDiagnostic) fun constraintError(error: ConstraintSystemError)
} }
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
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.TypeConstructor
@@ -223,12 +223,6 @@ class ArgumentTypeMismatchDiagnostic(
} }
} }
class OnlyInputTypesDiagnostic(val typeVariable: NewTypeVariable) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}
class ResolvedToSamWithVarargDiagnostic(val argument: KotlinCallArgument) : KotlinCallDiagnostic(RESOLVED_TO_SAM_WITH_VARARG) { class ResolvedToSamWithVarargDiagnostic(val argument: KotlinCallArgument) : KotlinCallDiagnostic(RESOLVED_TO_SAM_WITH_VARARG) {
override fun report(reporter: DiagnosticReporter) { override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(argument, this) reporter.onCallArgument(argument, this)
@@ -272,4 +266,16 @@ class AdaptedCallableReferenceIsUsedWithReflection(
reporter.onCallArgument(argument, this) reporter.onCallArgument(argument, this)
} }
} }
class KotlinConstraintSystemDiagnostic(
val error: ConstraintSystemError
) : KotlinCallDiagnostic(error.applicability) {
override fun report(reporter: DiagnosticReporter) = reporter.constraintError(error)
}
val KotlinCallDiagnostic.constraintSystemError: ConstraintSystemError?
get() = (this as? KotlinConstraintSystemDiagnostic)?.error
fun ConstraintSystemError.asDiagnostic(): KotlinConstraintSystemDiagnostic = KotlinConstraintSystemDiagnostic(this)
fun Collection<ConstraintSystemError>.asDiagnostics(): List<KotlinConstraintSystemDiagnostic> = map(ConstraintSystemError::asDiagnostic)
@@ -237,16 +237,17 @@ sealed class CallResolutionResult(
fun completedDiagnostic(substitutor: NewTypeSubstitutor): List<KotlinCallDiagnostic> { fun completedDiagnostic(substitutor: NewTypeSubstitutor): List<KotlinCallDiagnostic> {
return diagnostics.map { return diagnostics.map {
if (it !is NewConstraintError) return@map it val error = it.constraintSystemError ?: return@map it
val lowerType = it.lowerType.safeAs<KotlinType>()?.unwrap() ?: return@map it if (error !is NewConstraintError) return@map it
val lowerType = error.lowerType.safeAs<KotlinType>()?.unwrap() ?: return@map it
val newLowerType = substitutor.safeSubstitute(lowerType.unCapture()) val newLowerType = substitutor.safeSubstitute(lowerType.unCapture())
NewConstraintError(newLowerType, it.upperType, it.position) NewConstraintError(newLowerType, error.upperType, error.position).asDiagnostic()
} }
} }
override val atom: ResolutionAtom? get() = null override val atom: ResolutionAtom? get() = null
override fun toString() = "diagnostics: (${diagnostics.joinToString()})" override fun toString(): String = "diagnostics: (${diagnostics.joinToString()})"
} }
open class SingleCallResolutionResult( open class SingleCallResolutionResult(
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.components.*
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
@@ -62,6 +63,10 @@ fun KotlinDiagnosticsHolder.addDiagnosticIfNotNull(diagnostic: KotlinCallDiagnos
diagnostic?.let { addDiagnostic(it) } diagnostic?.let { addDiagnostic(it) }
} }
fun KotlinDiagnosticsHolder.addError(error: ConstraintSystemError) {
addDiagnostic(error.asDiagnostic())
}
/** /**
* baseSystem contains all information from arguments, i.e. it is union of all system of arguments * baseSystem contains all information from arguments, i.e. it is union of all system of arguments
* Also by convention we suppose that baseSystem has no contradiction * Also by convention we suppose that baseSystem has no contradiction
@@ -252,10 +257,10 @@ class MutableResolvedCallAtom(
fun KotlinResolutionCandidate.markCandidateForCompatibilityResolve() { fun KotlinResolutionCandidate.markCandidateForCompatibilityResolve() {
if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return
addDiagnostic(LowerPriorityToPreserveCompatibility) addDiagnostic(LowerPriorityToPreserveCompatibility.asDiagnostic())
} }
fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(diagnostics: SmartList<KotlinCallDiagnostic>) { fun CallableReferencesCandidateFactory.markCandidateForCompatibilityResolve(diagnostics: SmartList<KotlinCallDiagnostic>) {
if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return if (callComponents.languageVersionSettings.supportsFeature(LanguageFeature.DisableCompatibilityModeForNewInference)) return
diagnostics.add(LowerPriorityToPreserveCompatibility) diagnostics.add(LowerPriorityToPreserveCompatibility.asDiagnostic())
} }
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
import org.jetbrains.kotlin.resolve.calls.model.DiagnosticReporter import org.jetbrains.kotlin.resolve.calls.model.DiagnosticReporter
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.* import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
@@ -88,8 +89,13 @@ class CandidateWithBoundDispatchReceiver(
val diagnostics: List<ResolutionDiagnostic> val diagnostics: List<ResolutionDiagnostic>
) )
fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>) = @JvmName("getResultApplicabilityForConstraintErrors")
diagnostics.maxOfOrNull { it.candidateApplicability } ?: RESOLVED fun getResultApplicability(diagnostics: Collection<ConstraintSystemError>): ResolutionCandidateApplicability =
diagnostics.maxByOrNull { it.applicability }?.applicability ?: RESOLVED
@JvmName("getResultApplicabilityForCallDiagnostics")
fun getResultApplicability(diagnostics: Collection<KotlinCallDiagnostic>): ResolutionCandidateApplicability =
diagnostics.maxByOrNull { it.candidateApplicability }?.candidateApplicability ?: RESOLVED
enum class ResolutionCandidateApplicability { enum class ResolutionCandidateApplicability {
RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate