Introduce type parameter's upper bound aware type approximator for intersection types
This commit is contained in:
committed by
TeamCityServer
parent
750f327878
commit
6a78e0a10c
+20
-6
@@ -224,7 +224,8 @@ abstract class AbstractTypeApproximator(
|
||||
TypeApproximatorConfiguration.IntersectionStrategy.ALLOWED -> if (!thereIsApproximation) return null else intersectTypes(newTypes)
|
||||
TypeApproximatorConfiguration.IntersectionStrategy.TO_FIRST -> if (toSuper) newTypes.first() else return type.defaultResult(toSuper = false)
|
||||
// commonSupertypeCalculator should handle flexible types correctly
|
||||
TypeApproximatorConfiguration.IntersectionStrategy.TO_COMMON_SUPERTYPE -> {
|
||||
TypeApproximatorConfiguration.IntersectionStrategy.TO_COMMON_SUPERTYPE,
|
||||
TypeApproximatorConfiguration.IntersectionStrategy.TO_UPPER_BOUND_IF_SUPERTYPE -> {
|
||||
if (!toSuper) return type.defaultResult(toSuper = false)
|
||||
val resultType = commonSuperType(newTypes)
|
||||
approximateToSuperType(resultType, conf) ?: resultType
|
||||
@@ -449,13 +450,26 @@ abstract class AbstractTypeApproximator(
|
||||
* In<Foo> <: In<subType(Foo)>
|
||||
* Inv<in Foo> <: Inv<in subType(Foo)>
|
||||
*/
|
||||
val approximatedArgument = argumentType.let {
|
||||
if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
|
||||
approximateToSuperType(it, conf, depth)
|
||||
val approximatedArgument = if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
|
||||
val approximatedType = approximateToSuperType(argumentType, conf, depth)
|
||||
if (conf.intersection == TypeApproximatorConfiguration.IntersectionStrategy.TO_UPPER_BOUND_IF_SUPERTYPE
|
||||
&& argumentType.typeConstructor().isIntersection()
|
||||
&& parameter.getUpperBounds().all { AbstractTypeChecker.isSubtypeOf(ctx, argumentType, it) }
|
||||
) {
|
||||
val intersectedUpperBounds = intersectTypes(parameter.getUpperBounds())
|
||||
if (approximatedType == null
|
||||
|| !AbstractTypeChecker.isSubtypeOf(ctx, approximatedType, intersectedUpperBounds)
|
||||
) {
|
||||
intersectedUpperBounds
|
||||
} else {
|
||||
approximatedType
|
||||
}
|
||||
} else {
|
||||
approximateToSubType(it, conf, depth)
|
||||
approximatedType ?: continue@loop
|
||||
}
|
||||
} ?: continue@loop
|
||||
} else {
|
||||
approximateToSubType(argumentType, conf, depth) ?: continue@loop
|
||||
}
|
||||
|
||||
if (
|
||||
conf.intersection != TypeApproximatorConfiguration.IntersectionStrategy.ALLOWED &&
|
||||
|
||||
+7
-1
@@ -11,7 +11,8 @@ open class TypeApproximatorConfiguration {
|
||||
enum class IntersectionStrategy {
|
||||
ALLOWED,
|
||||
TO_FIRST,
|
||||
TO_COMMON_SUPERTYPE
|
||||
TO_COMMON_SUPERTYPE,
|
||||
TO_UPPER_BOUND_IF_SUPERTYPE
|
||||
}
|
||||
|
||||
open val flexible: Boolean get() = false // simple flexible types (FlexibleTypeImpl)
|
||||
@@ -87,4 +88,9 @@ open class TypeApproximatorConfiguration {
|
||||
|
||||
override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean = true
|
||||
}
|
||||
|
||||
object UpperBoundAwareIntersectionTypeApproximator : AllFlexibleSameValue() {
|
||||
override val allFlexible: Boolean get() = true
|
||||
override val intersection: IntersectionStrategy = IntersectionStrategy.TO_UPPER_BOUND_IF_SUPERTYPE
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user