Abstract TypeApproximator from NewCapturedType

This commit is contained in:
Simon Ogorodnik
2019-04-08 15:46:57 +03:00
parent 9306f3840f
commit 57a3b1a773
4 changed files with 30 additions and 13 deletions
@@ -46,8 +46,9 @@ open class TypeApproximatorConfiguration {
open val definitelyNotNullType get() = true open val definitelyNotNullType get() = true
open val intersection: IntersectionStrategy = TO_COMMON_SUPERTYPE open val intersection: IntersectionStrategy = TO_COMMON_SUPERTYPE
open val typeVariable: (TypeVariableTypeConstructor) -> Boolean = { false } open val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean = { false }
open val capturedType: (NewCapturedType) -> Boolean = { false } // true means that this type we can leave as is open fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
false // true means that this type we can leave as is
abstract class AllFlexibleSameValue : TypeApproximatorConfiguration() { abstract class AllFlexibleSameValue : TypeApproximatorConfiguration() {
abstract val allFlexible: Boolean abstract val allFlexible: Boolean
@@ -77,9 +78,11 @@ open class TypeApproximatorConfiguration {
override val errorType get() = true override val errorType get() = true
// i.e. will be approximated only approximatedCapturedStatus captured types // i.e. will be approximated only approximatedCapturedStatus captured types
override val capturedType get() = { it: NewCapturedType -> it.captureStatus != approximatedCapturedStatus } override fun capturedType(ctx: TypeSystemInferenceExtensionContext, type: CapturedTypeMarker): Boolean =
type.captureStatus(ctx) != approximatedCapturedStatus
override val intersection get() = IntersectionStrategy.ALLOWED override val intersection get() = IntersectionStrategy.ALLOWED
override val typeVariable: (TypeVariableTypeConstructor) -> Boolean get() = { true } override val typeVariable: (TypeVariableTypeConstructorMarker) -> Boolean get() = { true }
} }
object IncorporationConfiguration : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_INCORPORATION) object IncorporationConfiguration : TypeApproximatorConfiguration.AbstractCapturedTypesApproximation(FOR_INCORPORATION)
@@ -242,14 +245,14 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
} }
private fun approximateCapturedType( private fun approximateCapturedType(
type: NewCapturedType, type: CapturedTypeMarker,
conf: TypeApproximatorConfiguration, conf: TypeApproximatorConfiguration,
toSuper: Boolean, toSuper: Boolean,
depth: Int depth: Int
): KotlinTypeMarker? { ): KotlinTypeMarker? {
val supertypes = type.typeConstructor().supertypes() val supertypes = type.typeConstructor().supertypes()
val baseSuperType = when (supertypes.size) { val baseSuperType = when (supertypes.size) {
0 -> type.builtIns.nullableAnyType // Let C = in Int, then superType for C and C? is Any? 0 -> nullableAnyType() // Let C = in Int, then superType for C and C? is Any?
1 -> supertypes.single() 1 -> supertypes.single()
// Consider the following example: // Consider the following example:
@@ -271,9 +274,9 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
else -> type.typeConstructorProjection().getType()//.unwrap() else -> type.typeConstructorProjection().getType()//.unwrap()
} }
val baseSubType = type.lowerType ?: type.builtIns.nothingType val baseSubType = type.lowerType() ?: nothingType()
if (conf.capturedType(type)) { if (conf.capturedType(ctx, type)) {
/** /**
* Here everything is ok if bounds for this captured type should not be approximated. * Here everything is ok if bounds for this captured type should not be approximated.
* But. If such bounds contains some unauthorized types, then we cannot leave this captured type "as is". * But. If such bounds contains some unauthorized types, then we cannot leave this captured type "as is".
@@ -294,7 +297,7 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
// C = in Int, Int <: C => Int? <: C? // C = in Int, Int <: C => Int? <: C?
// C = out Number, C <: Number => C? <: Number? // C = out Number, C <: Number => C? <: Number?
return if (type.isMarkedNullable) baseResult.withNullability(true) else baseResult return if (type.isMarkedNullable()) baseResult.withNullability(true) else baseResult
} }
private fun approximateSimpleToSuperType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) = private fun approximateSimpleToSuperType(type: SimpleTypeMarker, conf: TypeApproximatorConfiguration, depth: Int) =
@@ -327,20 +330,21 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
val typeConstructor = type.typeConstructor() val typeConstructor = type.typeConstructor()
if (typeConstructor is NewCapturedTypeConstructor) { if (typeConstructor.isCapturedTypeConstructor()) {
assert(type is NewCapturedType) { val capturedType = type.asCapturedType()
require(capturedType != null) {
// KT-16147 // KT-16147
"Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " + "Type is inconsistent -- somewhere we create type with typeConstructor = $typeConstructor " +
"and class: ${type::class.java.canonicalName}. type.toString() = $type" "and class: ${type::class.java.canonicalName}. type.toString() = $type"
} }
return approximateCapturedType(type as NewCapturedType, conf, toSuper, depth) return approximateCapturedType(capturedType, conf, toSuper, depth)
} }
if (typeConstructor.isIntersection()) { if (typeConstructor.isIntersection()) {
return approximateIntersectionType(type, conf, toSuper, depth) return approximateIntersectionType(type, conf, toSuper, depth)
} }
if (typeConstructor is TypeVariableTypeConstructor) { if (typeConstructor is TypeVariableTypeConstructorMarker) {
return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper) return if (conf.typeVariable(typeConstructor)) null else type.defaultResult(toSuper)
} }
@@ -481,6 +481,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext {
require(constructor is TypeConstructor, constructor::errorMessage) require(constructor is TypeConstructor, constructor::errorMessage)
return ErrorUtils.createErrorTypeWithCustomConstructor(debugName, constructor) return ErrorUtils.createErrorTypeWithCustomConstructor(debugName, constructor)
} }
override fun TypeConstructorMarker.isCapturedTypeConstructor(): Boolean {
return this is NewCapturedTypeConstructor
}
} }
private fun captureFromExpressionInternal(type: UnwrappedType) = captureFromExpression(type) private fun captureFromExpressionInternal(type: UnwrappedType) = captureFromExpression(type)
@@ -22,4 +22,9 @@ fun KotlinTypeMarker.dependsOnTypeParameters(c: TypeSystemInferenceExtensionCont
with(c) { with(c) {
val typeConstructors = typeParameters.mapTo(mutableSetOf()) { it.getTypeConstructor() } val typeConstructors = typeParameters.mapTo(mutableSetOf()) { it.getTypeConstructor() }
dependsOnTypeConstructor(c, typeConstructors) dependsOnTypeConstructor(c, typeConstructors)
}
fun CapturedTypeMarker.captureStatus(c: TypeSystemInferenceExtensionContext) =
with(c) {
captureStatus()
} }
@@ -24,6 +24,7 @@ interface StubTypeMarker : SimpleTypeMarker
interface TypeArgumentListMarker interface TypeArgumentListMarker
interface TypeVariableMarker interface TypeVariableMarker
interface TypeVariableTypeConstructorMarker : TypeConstructorMarker
interface TypeSubstitutorMarker interface TypeSubstitutorMarker
@@ -88,6 +89,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker fun TypeConstructorMarker.getApproximatedIntegerLiteralType(): KotlinTypeMarker
fun TypeConstructorMarker.isCapturedTypeConstructor(): Boolean
fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker? fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker?
fun KotlinTypeMarker.isUnit(): Boolean fun KotlinTypeMarker.isUnit(): Boolean