Allow type variable fixation into intersection type if it isn't meaningless (i.e. has one or more final classes, or two or more open classes)

^KT-46186 Fixed
This commit is contained in:
Victor Petukhov
2021-04-20 14:41:13 +03:00
parent 310d98c4f7
commit 867d7b5bca
10 changed files with 312 additions and 4 deletions
@@ -216,10 +216,18 @@ class ResultTypeResolver(
variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperTypeForFixation(it.type) }
if (upperConstraints.isNotEmpty()) {
val intersectionUpperType = intersectTypes(upperConstraints.map { it.type })
val isThereExpectedTypeConstraint = upperConstraints.any { it.isExpectedTypePosition() }
val nonExpectedTypeConstraints = upperConstraints.filterNot { it.isExpectedTypePosition() }
val resultIsActuallyIntersection = intersectionUpperType.typeConstructor().isIntersection()
val upperType = if (isThereExpectedTypeConstraint && nonExpectedTypeConstraints.isNotEmpty() && resultIsActuallyIntersection) {
val isThereUnwantedIntersectedTypes = if (resultIsActuallyIntersection) {
val intersectionSupertypes = intersectionUpperType.typeConstructor().supertypes()
val intersectionClasses = intersectionSupertypes.count {
it.typeConstructor().isClassTypeConstructor() && !it.typeConstructor().isInterface()
}
val areThereIntersectionFinalClasses = intersectionSupertypes.any { it.typeConstructor().isCommonFinalClassConstructor() }
intersectionClasses > 1 || areThereIntersectionFinalClasses
} else false
val upperType = if (isThereUnwantedIntersectedTypes) {
/*
* We shouldn't infer a type variable into the intersection type if there is an explicit expected type,
* otherwise it can lead to something like this:
@@ -227,7 +235,7 @@ class ResultTypeResolver(
* fun <T : String> materialize(): T = null as T
* val bar: Int = materialize() // no errors, T is inferred into String & Int
*/
intersectTypes(nonExpectedTypeConstraints.map { it.type })
intersectTypes(upperConstraints.filterNot { it.isExpectedTypePosition() }.map { it.type })
} else intersectionUpperType
return typeApproximator.approximateToSubType(