NI: propagate isNullabilityConstraint flag into constraint injector and inherit it
^KT-37510 Fixed
This commit is contained in:
+24
-8
@@ -28,7 +28,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
||||
// super and sub type isSingleClassifierType
|
||||
abstract fun addUpperConstraint(typeVariable: TypeConstructorMarker, superType: KotlinTypeMarker)
|
||||
|
||||
abstract fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker)
|
||||
abstract fun addLowerConstraint(
|
||||
typeVariable: TypeConstructorMarker,
|
||||
subType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
)
|
||||
|
||||
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy {
|
||||
return when {
|
||||
@@ -52,7 +56,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
||||
* then we can get wrong result.
|
||||
* override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING
|
||||
*/
|
||||
final override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
|
||||
final override fun addSubtypeConstraint(
|
||||
subType: KotlinTypeMarker,
|
||||
superType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean
|
||||
): Boolean? {
|
||||
val hasNoInfer = subType.isTypeVariableWithNoInfer() || superType.isTypeVariableWithNoInfer()
|
||||
if (hasNoInfer) return true
|
||||
|
||||
@@ -64,10 +72,10 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
||||
val mySuperType =
|
||||
if (hasExact) extractTypeForProjectedType(superType, out = false) ?: superType.removeExactAnnotation() else superType
|
||||
|
||||
val result = internalAddSubtypeConstraint(mySubType, mySuperType)
|
||||
val result = internalAddSubtypeConstraint(mySubType, mySuperType, isFromNullabilityConstraint)
|
||||
if (!hasExact) return result
|
||||
|
||||
val result2 = internalAddSubtypeConstraint(mySuperType, mySubType)
|
||||
val result2 = internalAddSubtypeConstraint(mySuperType, mySubType, isFromNullabilityConstraint)
|
||||
|
||||
if (result == null && result2 == null) return null
|
||||
return (result ?: true) && (result2 ?: true)
|
||||
@@ -93,13 +101,17 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
||||
private fun KotlinTypeMarker.isTypeVariableWithNoInfer() =
|
||||
hasNoInferAnnotation() && anyBound(this@AbstractTypeCheckerContextForConstraintSystem::isMyTypeVariable)
|
||||
|
||||
private fun internalAddSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
|
||||
private fun internalAddSubtypeConstraint(
|
||||
subType: KotlinTypeMarker,
|
||||
superType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean
|
||||
): Boolean? {
|
||||
assertInputTypes(subType, superType)
|
||||
|
||||
var answer: Boolean? = null
|
||||
|
||||
if (superType.anyBound(this::isMyTypeVariable)) {
|
||||
answer = simplifyLowerConstraint(superType, subType)
|
||||
answer = simplifyLowerConstraint(superType, subType, isFromNullabilityConstraint)
|
||||
}
|
||||
|
||||
if (subType.anyBound(this::isMyTypeVariable)) {
|
||||
@@ -178,7 +190,11 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
||||
*
|
||||
* => (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T
|
||||
*/
|
||||
private fun simplifyLowerConstraint(typeVariable: KotlinTypeMarker, subType: KotlinTypeMarker): Boolean {
|
||||
private fun simplifyLowerConstraint(
|
||||
typeVariable: KotlinTypeMarker,
|
||||
subType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
): Boolean {
|
||||
val lowerConstraint = when (typeVariable) {
|
||||
is SimpleTypeMarker ->
|
||||
/*
|
||||
@@ -229,7 +245,7 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck
|
||||
else -> error("sealed")
|
||||
}
|
||||
|
||||
addLowerConstraint(typeVariable.typeConstructor(), lowerConstraint)
|
||||
addLowerConstraint(typeVariable.typeConstructor(), lowerConstraint, isFromNullabilityConstraint)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
+7
-3
@@ -31,7 +31,8 @@ class ConstraintIncorporator(
|
||||
fun addNewIncorporatedConstraint(
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
)
|
||||
|
||||
fun addNewIncorporatedConstraint(typeVariable: TypeVariableMarker, type: KotlinTypeMarker, constraintContext: ConstraintContext)
|
||||
@@ -62,7 +63,7 @@ class ConstraintIncorporator(
|
||||
if (constraint.kind != ConstraintKind.LOWER) {
|
||||
getConstraintsForVariable(typeVariable).forEach {
|
||||
if (it.kind != ConstraintKind.UPPER) {
|
||||
addNewIncorporatedConstraint(it.type, constraint.type, shouldBeTypeVariableFlexible)
|
||||
addNewIncorporatedConstraint(it.type, constraint.type, shouldBeTypeVariableFlexible, it.isNullabilityConstraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +232,10 @@ class ConstraintIncorporator(
|
||||
|
||||
val inputTypePosition = baseConstraint.position.from.safeAs<OnlyInputTypeConstraintPosition>()
|
||||
|
||||
val isNullabilityConstraint = isUsefulForNullabilityConstraint && newConstraint.isNullableNothing()
|
||||
val isNewConstraintUsefulForNullability = isUsefulForNullabilityConstraint && newConstraint.isNullableNothing()
|
||||
val isOtherConstraintUsefulForNullability = otherConstraint.isNullabilityConstraint && otherConstraint.type.isNullableNothing()
|
||||
val isNullabilityConstraint = isNewConstraintUsefulForNullability || isOtherConstraintUsefulForNullability
|
||||
|
||||
val constraintContext = ConstraintContext(kind, derivedFrom, inputTypePosition, isNullabilityConstraint)
|
||||
|
||||
addNewIncorporatedConstraint(targetVariable, newConstraint, constraintContext)
|
||||
|
||||
+23
-8
@@ -181,13 +181,15 @@ class ConstraintInjector(
|
||||
fun runIsSubtypeOf(
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean = false
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean = false,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
) {
|
||||
fun isSubtypeOf(upperType: KotlinTypeMarker) =
|
||||
AbstractTypeChecker.isSubtypeOf(
|
||||
this@TypeCheckerContext as AbstractTypeCheckerContext,
|
||||
lowerType,
|
||||
upperType
|
||||
upperType,
|
||||
isFromNullabilityConstraint
|
||||
)
|
||||
|
||||
if (!isSubtypeOf(upperType)) {
|
||||
@@ -215,8 +217,11 @@ class ConstraintInjector(
|
||||
override fun addUpperConstraint(typeVariable: TypeConstructorMarker, superType: KotlinTypeMarker) =
|
||||
addConstraint(typeVariable, superType, UPPER)
|
||||
|
||||
override fun addLowerConstraint(typeVariable: TypeConstructorMarker, subType: KotlinTypeMarker) =
|
||||
addConstraint(typeVariable, subType, LOWER)
|
||||
override fun addLowerConstraint(
|
||||
typeVariable: TypeConstructorMarker,
|
||||
subType: KotlinTypeMarker,
|
||||
isFromNullabilityConstraint: Boolean
|
||||
) = addConstraint(typeVariable, subType, LOWER, isFromNullabilityConstraint)
|
||||
|
||||
private fun isCapturedTypeFromSubtyping(type: KotlinTypeMarker) =
|
||||
when ((type as? CapturedTypeMarker)?.captureStatus()) {
|
||||
@@ -226,22 +231,32 @@ class ConstraintInjector(
|
||||
error("Captured type for incorporation shouldn't escape from incorporation: $type\n" + renderBaseConstraint())
|
||||
}
|
||||
|
||||
private fun addConstraint(typeVariableConstructor: TypeConstructorMarker, type: KotlinTypeMarker, kind: ConstraintKind) {
|
||||
private fun addConstraint(
|
||||
typeVariableConstructor: TypeConstructorMarker,
|
||||
type: KotlinTypeMarker,
|
||||
kind: ConstraintKind,
|
||||
isFromNullabilityConstraint: Boolean = false
|
||||
) {
|
||||
val typeVariable = c.allTypeVariables[typeVariableConstructor]
|
||||
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
|
||||
|
||||
addNewIncorporatedConstraint(typeVariable, type, ConstraintContext(kind, emptySet(), isNullabilityConstraint = false))
|
||||
addNewIncorporatedConstraint(
|
||||
typeVariable,
|
||||
type,
|
||||
ConstraintContext(kind, emptySet(), isNullabilityConstraint = isFromNullabilityConstraint)
|
||||
)
|
||||
}
|
||||
|
||||
// from ConstraintIncorporator.Context
|
||||
override fun addNewIncorporatedConstraint(
|
||||
lowerType: KotlinTypeMarker,
|
||||
upperType: KotlinTypeMarker,
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean
|
||||
shouldTryUseDifferentFlexibilityForUpperType: Boolean,
|
||||
isFromNullabilityConstraint: Boolean
|
||||
) {
|
||||
if (lowerType === upperType) return
|
||||
if (c.isAllowedType(lowerType) && c.isAllowedType(upperType)) {
|
||||
runIsSubtypeOf(lowerType, upperType, shouldTryUseDifferentFlexibilityForUpperType)
|
||||
runIsSubtypeOf(lowerType, upperType, shouldTryUseDifferentFlexibilityForUpperType, isFromNullabilityConstraint)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user