[NI] Do not avoid trivial constraints if they aren't from upper bounds
Since we skipped trivial constraint with `Any?` from parameter type of function `equals`, the compiler thought that there is no proper constraints (upper bounds do not matter here) and marked resolved call as a failed one, then diagnostic about missing equals was added Also, tune `TrivialConstraintTypeInferenceOracle` for `Any?`-like constraints #KT-30724 Fixed
This commit is contained in:
+2
-3
@@ -201,9 +201,8 @@ class KotlinCallCompleter(
|
||||
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
|
||||
val constraints = variableWithConstraints.constraints
|
||||
return constraints.isNotEmpty() && constraints.all {
|
||||
!trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) &&
|
||||
with(context) { !it.type.typeConstructor().isIntegerLiteralTypeConstructor() } &&
|
||||
it.kind.isLower() && csBuilder.isProperType(it.type)
|
||||
with(context) { !it.type.typeConstructor().isIntegerLiteralTypeConstructor() } &&
|
||||
it.kind.isLower() && csBuilder.isProperType(it.type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-2
@@ -156,13 +156,19 @@ class ConstraintIncorporator(
|
||||
|
||||
if (baseConstraint.kind != ConstraintKind.UPPER) {
|
||||
val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = false)
|
||||
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) {
|
||||
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(
|
||||
otherConstraint, generatedConstraintType, isSubtype = true
|
||||
)
|
||||
) {
|
||||
addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType())
|
||||
}
|
||||
}
|
||||
if (baseConstraint.kind != ConstraintKind.LOWER) {
|
||||
val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = true)
|
||||
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) {
|
||||
if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(
|
||||
otherConstraint, generatedConstraintType, isSubtype = false
|
||||
)
|
||||
) {
|
||||
addNewIncorporatedConstraint(targetVariable.defaultType(), generatedConstraintType)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -101,7 +101,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
}
|
||||
|
||||
if (constraintType.isSimpleType()) {
|
||||
if (constraint.kind == UPPER && constraintType.isNullableAny()) return true // T <: Any?
|
||||
if (constraint.position.from is DeclaredUpperBoundConstraintPosition &&
|
||||
constraint.kind == UPPER && constraintType.isNullableAny()
|
||||
) {
|
||||
return true // T <: Any?
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
+10
-8
@@ -7,19 +7,19 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||
|
||||
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.NewTypeVariable
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableNothing
|
||||
|
||||
class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtensionContextDelegate) :
|
||||
TypeSystemInferenceExtensionContext by context {
|
||||
// The idea is to add knowledge that constraint `Nothing(?) <: T` is quite useless and
|
||||
// it's totally fine to go and resolve postponed argument without fixation T to Nothing(?).
|
||||
// In other words, constraint `Nothing(?) <: T` is *not* proper
|
||||
fun isTrivialConstraint(
|
||||
constraint: Constraint
|
||||
): Boolean {
|
||||
// TODO: probably we also can take into account `T <: Any(?)` constraints
|
||||
fun isNotInterestingConstraint(constraint: Constraint): Boolean {
|
||||
return constraint.kind == ConstraintKind.LOWER && constraint.type.typeConstructor().isNothingConstructor()
|
||||
}
|
||||
|
||||
@@ -39,9 +39,11 @@ class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtension
|
||||
// Therefore, here we avoid adding such trivial constraints to have stable constraint system
|
||||
fun isGeneratedConstraintTrivial(
|
||||
otherConstraint: Constraint,
|
||||
generatedConstraintType: KotlinTypeMarker
|
||||
generatedConstraintType: KotlinTypeMarker,
|
||||
isSubtype: Boolean
|
||||
): Boolean {
|
||||
if (generatedConstraintType.isNothing()) return true
|
||||
if (isSubtype && generatedConstraintType.isNothing()) return true
|
||||
if (!isSubtype && generatedConstraintType.isNullableAny()) return true
|
||||
|
||||
// If type that will be used to generate new constraint already contains `Nothing(?)`,
|
||||
// then we can't decide that resulting constraint will be useless
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ class VariableFixationFinder(
|
||||
private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean {
|
||||
return notFixedTypeVariables[variable]?.constraints?.all { constraint ->
|
||||
val isProperConstraint = isProperArgumentConstraint(constraint)
|
||||
isProperConstraint && trivialConstraintTypeInferenceOracle.isTrivialConstraint(constraint) || !isProperConstraint
|
||||
isProperConstraint && trivialConstraintTypeInferenceOracle.isNotInterestingConstraint(constraint) || !isProperConstraint
|
||||
} ?: false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user