Approximate types when only input types check is done. Otherwise given types are inconsistent with types obtained by ResultTypeResolver
^KT-45714 Fixed
This commit is contained in:
+2
-2
@@ -32,12 +32,12 @@ class MutableVariableWithConstraints private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// see @OnlyInputTypes annotation
|
// see @OnlyInputTypes annotation
|
||||||
fun getProjectedInputCallTypes(utilContext: ConstraintSystemUtilContext): Collection<KotlinTypeMarker> {
|
fun getProjectedInputCallTypes(utilContext: ConstraintSystemUtilContext): Collection<Pair<KotlinTypeMarker, ConstraintKind>> {
|
||||||
return with(utilContext) {
|
return with(utilContext) {
|
||||||
mutableConstraints
|
mutableConstraints
|
||||||
.mapNotNullTo(SmartList()) {
|
.mapNotNullTo(SmartList()) {
|
||||||
if (it.position.from is OnlyInputTypeConstraintPosition || it.inputTypePositionBeforeIncorporation != null)
|
if (it.position.from is OnlyInputTypeConstraintPosition || it.inputTypePositionBeforeIncorporation != null)
|
||||||
it.type.unCapture()
|
it.type.unCapture() to it.kind
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-9
@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.resolve.calls.inference.model
|
|||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.*
|
import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
@@ -361,24 +363,41 @@ class NewConstraintSystemImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinTypeMarker.substituteIfNecessary(substitutor: TypeSubstitutorMarker): KotlinTypeMarker {
|
private fun KotlinTypeMarker.substituteAndApproximateIfNecessary(
|
||||||
|
substitutor: TypeSubstitutorMarker,
|
||||||
|
approximator: AbstractTypeApproximator,
|
||||||
|
constraintKind: ConstraintKind
|
||||||
|
): KotlinTypeMarker {
|
||||||
val doesInputTypeContainsOtherVariables = this.contains { it.typeConstructor() is TypeVariableTypeConstructorMarker }
|
val doesInputTypeContainsOtherVariables = this.contains { it.typeConstructor() is TypeVariableTypeConstructorMarker }
|
||||||
return if (doesInputTypeContainsOtherVariables) substitutor.safeSubstitute(this) else this
|
val substitutedType = if (doesInputTypeContainsOtherVariables) substitutor.safeSubstitute(this) else this
|
||||||
|
// Appoximation here is the same as ResultTypeResolver do
|
||||||
|
val approximatedType = when (constraintKind) {
|
||||||
|
ConstraintKind.LOWER ->
|
||||||
|
approximator.approximateToSuperType(substitutedType, TypeApproximatorConfiguration.InternalTypesApproximation)
|
||||||
|
ConstraintKind.UPPER ->
|
||||||
|
approximator.approximateToSubType(substitutedType, TypeApproximatorConfiguration.InternalTypesApproximation)
|
||||||
|
ConstraintKind.EQUALITY -> substitutedType
|
||||||
|
} ?: substitutedType
|
||||||
|
|
||||||
|
return approximatedType
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkOnlyInputTypesAnnotation(variableWithConstraints: MutableVariableWithConstraints, resultType: KotlinTypeMarker) {
|
private fun checkOnlyInputTypesAnnotation(variableWithConstraints: MutableVariableWithConstraints, resultType: KotlinTypeMarker) {
|
||||||
val substitutor = buildCurrentSubstitutor()
|
val substitutor = buildCurrentSubstitutor()
|
||||||
val isResultTypeEqualSomeInputType = variableWithConstraints.getProjectedInputCallTypes(utilContext).any { inputType ->
|
val approximator = constraintInjector.typeApproximator
|
||||||
val inputTypeConstructor = inputType.typeConstructor()
|
val isResultTypeEqualSomeInputType =
|
||||||
|
variableWithConstraints.getProjectedInputCallTypes(utilContext).any { (inputType, constraintKind) ->
|
||||||
|
val inputTypeConstructor = inputType.typeConstructor()
|
||||||
|
val otherResultType = inputType.substituteAndApproximateIfNecessary(substitutor, approximator, constraintKind)
|
||||||
|
|
||||||
|
if (AbstractTypeChecker.equalTypes(this, resultType, otherResultType)) return@any true
|
||||||
|
if (!inputTypeConstructor.isIntersection()) return@any false
|
||||||
|
|
||||||
if (inputTypeConstructor.isIntersection()) {
|
|
||||||
inputTypeConstructor.supertypes().any {
|
inputTypeConstructor.supertypes().any {
|
||||||
AbstractTypeChecker.equalTypes(this, resultType, it.substituteIfNecessary(substitutor))
|
val intersectionComponentResultType = it.substituteAndApproximateIfNecessary(substitutor, approximator, constraintKind)
|
||||||
|
AbstractTypeChecker.equalTypes(this, resultType, intersectionComponentResultType)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
AbstractTypeChecker.equalTypes(this, resultType, inputType.substituteIfNecessary(substitutor))
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!isResultTypeEqualSomeInputType) {
|
if (!isResultTypeEqualSomeInputType) {
|
||||||
addError(OnlyInputTypesDiagnostic(variableWithConstraints.typeVariable))
|
addError(OnlyInputTypesDiagnostic(variableWithConstraints.typeVariable))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user