[NI] Avoid building controversial systems by clipping extra constraints
#KT-23854 Fixed
This commit is contained in:
+37
-6
@@ -12,9 +12,12 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empt
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.forceResolution
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.IntersectionTypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||
|
||||
class KotlinCallCompleter(
|
||||
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
|
||||
@@ -160,12 +163,40 @@ class KotlinCallCompleter(
|
||||
// This is questionable as null return type can be only for error call
|
||||
if (currentReturnType == null) return ConstraintSystemCompletionMode.PARTIAL
|
||||
|
||||
// Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode
|
||||
// Otherwise, we shouldn't complete bar until we process call foo
|
||||
return if (csBuilder.isProperType(currentReturnType))
|
||||
ConstraintSystemCompletionMode.FULL
|
||||
else
|
||||
ConstraintSystemCompletionMode.PARTIAL
|
||||
return when {
|
||||
// Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode
|
||||
// Otherwise, we shouldn't complete bar until we process call foo
|
||||
csBuilder.isProperType(currentReturnType) -> ConstraintSystemCompletionMode.FULL
|
||||
|
||||
// Nested call is connected with the outer one through the UPPER constraint (returnType <: expectedOuterType)
|
||||
// This means that there will be no new LOWER constraints =>
|
||||
// it's possible to complete call now if there are proper LOWER constraints
|
||||
csBuilder.isTypeVariable(currentReturnType) ->
|
||||
if (hasProperLowerConstraints(currentReturnType))
|
||||
ConstraintSystemCompletionMode.FULL
|
||||
else
|
||||
ConstraintSystemCompletionMode.PARTIAL
|
||||
|
||||
else -> ConstraintSystemCompletionMode.PARTIAL
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.hasProperLowerConstraints(typeVariable: UnwrappedType): Boolean {
|
||||
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
|
||||
|
||||
val constructor = typeVariable.constructor
|
||||
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
|
||||
return variableWithConstraints.constraints.any {
|
||||
it.kind.isLower() && csBuilder.isProperType(it.type) && !it.type.isIntegerValueType()
|
||||
}
|
||||
}
|
||||
|
||||
private fun UnwrappedType.isIntegerValueType(): Boolean {
|
||||
if (constructor is IntegerValueTypeConstructor) return true
|
||||
if (constructor is IntersectionTypeConstructor)
|
||||
return constructor.supertypes.all { it.isPrimitiveNumberType() }
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.computeReturnTypeWithSmartCastInfo(
|
||||
|
||||
+5
-1
@@ -60,7 +60,11 @@ interface ConstraintStorage {
|
||||
enum class ConstraintKind {
|
||||
LOWER,
|
||||
UPPER,
|
||||
EQUALITY
|
||||
EQUALITY;
|
||||
|
||||
fun isLower(): Boolean = this == LOWER
|
||||
fun isUpper(): Boolean = this == UPPER
|
||||
fun isEqual(): Boolean = this == EQUALITY
|
||||
}
|
||||
|
||||
class Constraint(
|
||||
|
||||
Reference in New Issue
Block a user