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.ALLOWED -> if (!thereIsApproximation) return null else intersectTypes(newTypes)
|
||||||
TypeApproximatorConfiguration.IntersectionStrategy.TO_FIRST -> if (toSuper) newTypes.first() else return type.defaultResult(toSuper = false)
|
TypeApproximatorConfiguration.IntersectionStrategy.TO_FIRST -> if (toSuper) newTypes.first() else return type.defaultResult(toSuper = false)
|
||||||
// commonSupertypeCalculator should handle flexible types correctly
|
// 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)
|
if (!toSuper) return type.defaultResult(toSuper = false)
|
||||||
val resultType = commonSuperType(newTypes)
|
val resultType = commonSuperType(newTypes)
|
||||||
approximateToSuperType(resultType, conf) ?: resultType
|
approximateToSuperType(resultType, conf) ?: resultType
|
||||||
@@ -449,13 +450,26 @@ abstract class AbstractTypeApproximator(
|
|||||||
* In<Foo> <: In<subType(Foo)>
|
* In<Foo> <: In<subType(Foo)>
|
||||||
* Inv<in Foo> <: Inv<in subType(Foo)>
|
* Inv<in Foo> <: Inv<in subType(Foo)>
|
||||||
*/
|
*/
|
||||||
val approximatedArgument = argumentType.let {
|
val approximatedArgument = if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
|
||||||
if (isApproximateDirectionToSuper(effectiveVariance, toSuper)) {
|
val approximatedType = approximateToSuperType(argumentType, conf, depth)
|
||||||
approximateToSuperType(it, 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 {
|
} else {
|
||||||
approximateToSubType(it, conf, depth)
|
approximatedType ?: continue@loop
|
||||||
}
|
}
|
||||||
} ?: continue@loop
|
} else {
|
||||||
|
approximateToSubType(argumentType, conf, depth) ?: continue@loop
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
conf.intersection != TypeApproximatorConfiguration.IntersectionStrategy.ALLOWED &&
|
conf.intersection != TypeApproximatorConfiguration.IntersectionStrategy.ALLOWED &&
|
||||||
|
|||||||
+7
-1
@@ -11,7 +11,8 @@ open class TypeApproximatorConfiguration {
|
|||||||
enum class IntersectionStrategy {
|
enum class IntersectionStrategy {
|
||||||
ALLOWED,
|
ALLOWED,
|
||||||
TO_FIRST,
|
TO_FIRST,
|
||||||
TO_COMMON_SUPERTYPE
|
TO_COMMON_SUPERTYPE,
|
||||||
|
TO_UPPER_BOUND_IF_SUPERTYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
open val flexible: Boolean get() = false // simple flexible types (FlexibleTypeImpl)
|
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
|
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