Don't fix a type variable into the intersection type if there is an explicit expected type

^KT-43303 Fixed
^KT-42396 Fixed
^KT-42472 Fixed
This commit is contained in:
Victor Petukhov
2021-03-03 16:02:10 +03:00
parent e06bacafad
commit 7f7bb70596
18 changed files with 220 additions and 6 deletions
@@ -215,7 +215,20 @@ class ResultTypeResolver(
val upperConstraints =
variableWithConstraints.constraints.filter { it.kind == ConstraintKind.UPPER && this@findSuperType.isProperTypeForFixation(it.type) }
if (upperConstraints.isNotEmpty()) {
val upperType = intersectTypes(upperConstraints.map { it.type })
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) {
/*
* 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:
*
* 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 })
} else intersectionUpperType
return typeApproximator.approximateToSubType(
upperType,
@@ -106,3 +106,6 @@ class ConstrainingTypeIsError(
class OnlyInputTypesDiagnostic(val typeVariable: TypeVariableMarker) : ConstraintSystemError(INAPPLICABLE)
object LowerPriorityToPreserveCompatibility : ConstraintSystemError(RESOLVED_NEED_PRESERVE_COMPATIBILITY)
fun Constraint.isExpectedTypePosition() =
position.from is ExpectedTypeConstraintPosition<*> || position.from is DelegatedPropertyConstraintPosition<*>