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:
+12
-4
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user