NI: decrease fixation priority for variables which have only incorporated from upper bound constraints
^KT-40045 Fixed ^KT-39633 Fixed
This commit is contained in:
+13
-4
@@ -33,7 +33,8 @@ class ConstraintIncorporator(
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
isFromNullabilityConstraint: Boolean = false,
|
||||
isFromDeclaredUpperBound: Boolean = false
|
||||
)
|
||||
|
||||
fun addNewIncorporatedConstraint(typeVariable: TypeVariableMarker, type: KotlinTypeMarker, constraintContext: ConstraintContext)
|
||||
@@ -80,7 +81,15 @@ class ConstraintIncorporator(
|
||||
if (constraint.kind != ConstraintKind.UPPER) {
|
||||
getConstraintsForVariable(typeVariable).forEach {
|
||||
if (it.kind != ConstraintKind.LOWER) {
|
||||
addNewIncorporatedConstraint(constraint.type, it.type, shouldBeTypeVariableFlexible)
|
||||
val isFromDeclaredUpperBound =
|
||||
it.position.from is DeclaredUpperBoundConstraintPosition && it.type.typeConstructor() !is TypeVariableTypeConstructor
|
||||
|
||||
addNewIncorporatedConstraint(
|
||||
constraint.type,
|
||||
it.type,
|
||||
shouldBeTypeVariableFlexible,
|
||||
isFromDeclaredUpperBound = isFromDeclaredUpperBound
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,7 +259,7 @@ class ConstraintIncorporator(
|
||||
addNewIncorporatedConstraint(targetVariable, newConstraint, constraintContext)
|
||||
}
|
||||
|
||||
fun Context.containsConstrainingTypeWithoutProjection(
|
||||
private fun Context.containsConstrainingTypeWithoutProjection(
|
||||
newConstraint: KotlinTypeMarker,
|
||||
otherConstraint: Constraint
|
||||
): Boolean {
|
||||
@@ -274,7 +283,7 @@ class ConstraintIncorporator(
|
||||
return otherConstraintCanAddNullabilityToNewOne || newConstraintCanAddNullabilityToOtherOne
|
||||
}
|
||||
|
||||
fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> =
|
||||
private fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> =
|
||||
getNestedArguments(type).mapNotNullTo(SmartList()) { getTypeVariable(it.getType().typeConstructor()) }
|
||||
|
||||
|
||||
|
||||
+16
-2
@@ -144,6 +144,8 @@ class ConstraintInjector(
|
||||
private var baseLowerType = position.initialConstraint.a
|
||||
private var baseUpperType = position.initialConstraint.b
|
||||
|
||||
private var isIncorporatingConstraintFromDeclaredUpperBound = false
|
||||
|
||||
fun extractAllConstraints() = possibleNewConstraints.also { possibleNewConstraints = null }
|
||||
|
||||
fun addPossibleNewConstraint(variable: TypeVariableMarker, constraint: Constraint) {
|
||||
@@ -252,16 +254,26 @@ class ConstraintInjector(
|
||||
)
|
||||
}
|
||||
|
||||
private fun addNewIncorporatedConstraintFromDeclaredUpperBound(runIsSubtypeOf: Runnable) {
|
||||
isIncorporatingConstraintFromDeclaredUpperBound = true
|
||||
runIsSubtypeOf.run()
|
||||
isIncorporatingConstraintFromDeclaredUpperBound = false
|
||||
}
|
||||
|
||||
// from ConstraintIncorporator.Context
|
||||
override fun addNewIncorporatedConstraint(
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean,
|
||||
isFromNullabilityConstraint: Boolean
|
||||
isFromNullabilityConstraint: Boolean,
|
||||
isFromDeclaredUpperBound: Boolean
|
||||
) {
|
||||
if (lowerType === upperType) return
|
||||
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
|
||||
runIsSubtypeOf(lowerType, upperType, shouldTryUseDifferentFlexibilityForUpperType, isFromNullabilityConstraint)
|
||||
fun runIsSubtypeOf() =
|
||||
runIsSubtypeOf(lowerType, upperType, shouldTryUseDifferentFlexibilityForUpperType, isFromNullabilityConstraint)
|
||||
|
||||
if (isFromDeclaredUpperBound) addNewIncorporatedConstraintFromDeclaredUpperBound(::runIsSubtypeOf) else runIsSubtypeOf()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,6 +319,8 @@ class ConstraintInjector(
|
||||
}
|
||||
}
|
||||
|
||||
val position = if (isIncorporatingConstraintFromDeclaredUpperBound) position.copy(isFromDeclaredUpperBound = true) else position
|
||||
|
||||
val newConstraint = Constraint(
|
||||
kind, targetType, position,
|
||||
derivedFrom = derivedFrom,
|
||||
|
||||
+8
-20
@@ -279,12 +279,12 @@ class KotlinConstraintSystemCompleter(
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder
|
||||
): Boolean {
|
||||
while (true) {
|
||||
val variableForFixation = getVariableReadyForFixation(
|
||||
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
||||
this,
|
||||
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
||||
postponedArguments,
|
||||
completionMode,
|
||||
topLevelAtoms,
|
||||
topLevelType,
|
||||
collectVariablesFromContext,
|
||||
postponedArguments
|
||||
topLevelType
|
||||
) ?: break
|
||||
|
||||
if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL)
|
||||
@@ -383,27 +383,15 @@ class KotlinConstraintSystemCompleter(
|
||||
return result.toList()
|
||||
}
|
||||
|
||||
private fun Context.getVariableReadyForFixation(
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelAtoms: List<ResolvedAtom>,
|
||||
topLevelType: UnwrappedType,
|
||||
collectVariablesFromContext: Boolean,
|
||||
postponedArguments: List<PostponedResolvedAtom>
|
||||
) = variableFixationFinder.findFirstVariableForFixation(
|
||||
this,
|
||||
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
||||
postponedArguments,
|
||||
completionMode,
|
||||
topLevelType
|
||||
)
|
||||
|
||||
private fun Context.isThereAnyReadyForFixationVariable(
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelAtoms: List<ResolvedAtom>,
|
||||
topLevelType: UnwrappedType,
|
||||
collectVariablesFromContext: Boolean,
|
||||
postponedArguments: List<PostponedResolvedAtom>
|
||||
) = getVariableReadyForFixation(completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments) != null
|
||||
) = variableFixationFinder.findFirstVariableForFixation(
|
||||
this, getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms), postponedArguments, completionMode, topLevelType
|
||||
) != null
|
||||
|
||||
companion object {
|
||||
fun getOrderedNotAnalyzedPostponedArguments(topLevelAtoms: List<ResolvedAtom>): List<PostponedResolvedAtom> {
|
||||
|
||||
+12
-5
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
||||
@@ -57,6 +56,7 @@ class VariableFixationFinder(
|
||||
WITH_COMPLEX_DEPENDENCY, // if type variable T has constraint with non fixed type variable inside (non-top-level): T <: Foo<S>
|
||||
WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS, // proper trivial constraint from arguments, Nothing <: T
|
||||
RELATED_TO_ANY_OUTPUT_TYPE,
|
||||
FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND,
|
||||
READY_FOR_FIXATION,
|
||||
READY_FOR_FIXATION_REIFIED,
|
||||
}
|
||||
@@ -71,6 +71,8 @@ class VariableFixationFinder(
|
||||
hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY
|
||||
variableHasTrivialOrNonProperConstraints(variable) -> TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS
|
||||
dependencyProvider.isVariableRelatedToAnyOutputType(variable) -> TypeVariableFixationReadiness.RELATED_TO_ANY_OUTPUT_TYPE
|
||||
variableHasOnlyIncorporatedConstraintsFromDeclaredUpperBound(variable) ->
|
||||
TypeVariableFixationReadiness.FROM_INCORPORATION_OF_DECLARED_UPPER_BOUND
|
||||
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
|
||||
else -> TypeVariableFixationReadiness.READY_FOR_FIXATION
|
||||
}
|
||||
@@ -87,13 +89,19 @@ class VariableFixationFinder(
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean {
|
||||
private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean {
|
||||
return notFixedTypeVariables[variable]?.constraints?.all { constraint ->
|
||||
val isProperConstraint = isProperArgumentConstraint(constraint)
|
||||
isProperConstraint && trivialConstraintTypeInferenceOracle.isNotInterestingConstraint(constraint) || !isProperConstraint
|
||||
} ?: false
|
||||
}
|
||||
|
||||
private fun Context.variableHasOnlyIncorporatedConstraintsFromDeclaredUpperBound(variable: TypeConstructorMarker): Boolean {
|
||||
val constraints = notFixedTypeVariables[variable]?.constraints ?: return false
|
||||
|
||||
return constraints.filter { isProperArgumentConstraint(it) }.all { it.position.isFromDeclaredUpperBound }
|
||||
}
|
||||
|
||||
private fun Context.findTypeVariableForFixation(
|
||||
allTypeVariables: List<TypeConstructorMarker>,
|
||||
postponedArguments: List<PostponedResolvedAtomMarker>,
|
||||
@@ -106,10 +114,9 @@ class VariableFixationFinder(
|
||||
notFixedTypeVariables, postponedArguments, topLevelType.takeIf { completionMode == PARTIAL }, this
|
||||
)
|
||||
|
||||
val candidate = allTypeVariables.maxBy { getTypeVariableReadiness(it, dependencyProvider) } ?: return null
|
||||
val candidate = allTypeVariables.maxByOrNull { getTypeVariableReadiness(it, dependencyProvider) } ?: return null
|
||||
|
||||
val candidateReadiness = getTypeVariableReadiness(candidate, dependencyProvider)
|
||||
return when (candidateReadiness) {
|
||||
return when (getTypeVariableReadiness(candidate, dependencyProvider)) {
|
||||
TypeVariableFixationReadiness.FORBIDDEN -> null
|
||||
TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> VariableForFixation(candidate, false)
|
||||
TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS ->
|
||||
|
||||
+3
-2
@@ -81,9 +81,10 @@ class DelegatedPropertyConstraintPosition(val topLevelCall: KotlinCall) : Constr
|
||||
override fun toString() = "Constraint from call $topLevelCall for delegated property"
|
||||
}
|
||||
|
||||
class IncorporationConstraintPosition(
|
||||
data class IncorporationConstraintPosition(
|
||||
val from: ConstraintPosition,
|
||||
val initialConstraint: InitialConstraint
|
||||
val initialConstraint: InitialConstraint,
|
||||
var isFromDeclaredUpperBound: Boolean = false
|
||||
) : ConstraintPosition() {
|
||||
override fun toString() =
|
||||
"Incorporate $initialConstraint from position $from"
|
||||
|
||||
Reference in New Issue
Block a user