[API Usage] Inject Refiner into KotlinTypeChecker, use it for subtyping
This commit is contained in:
committed by
Dmitry Savvinov
parent
9047ddfc2f
commit
a1b52b2f90
+14
-2
@@ -22,11 +22,23 @@ import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker.transformToNewTyp
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
|
||||
open class ClassicTypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowedTypeVariable: Boolean = true) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
|
||||
open class ClassicTypeCheckerContext(
|
||||
val errorTypeEqualsToAnything: Boolean,
|
||||
val allowedTypeVariable: Boolean = true,
|
||||
val kotlinTypeRefiner: KotlinTypeRefiner = KotlinTypeRefiner.Default
|
||||
) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
|
||||
|
||||
override fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return transformToNewType((type as KotlinType).unwrap())
|
||||
require(type is KotlinType, type::errorMessage)
|
||||
return transformToNewType(type.unwrap())
|
||||
}
|
||||
|
||||
@UseExperimental(TypeRefinement::class)
|
||||
override fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
require(type is KotlinType, type::errorMessage)
|
||||
return kotlinTypeRefiner.refineType(type)
|
||||
}
|
||||
|
||||
override val isErrorTypeEqualsToAnything: Boolean
|
||||
|
||||
@@ -56,20 +56,24 @@ object ErrorTypesAreEqualToAnything : KotlinTypeChecker {
|
||||
}
|
||||
|
||||
interface NewKotlinTypeChecker : KotlinTypeChecker {
|
||||
val kotlinTypeRefiner: KotlinTypeRefiner
|
||||
|
||||
fun transformToNewType(type: UnwrappedType): UnwrappedType
|
||||
|
||||
companion object {
|
||||
val Default = NewKotlinTypeCheckerImpl()
|
||||
val Default = NewKotlinTypeCheckerImpl(KotlinTypeRefiner.Default)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class NewKotlinTypeCheckerImpl() : NewKotlinTypeChecker {
|
||||
class NewKotlinTypeCheckerImpl(override val kotlinTypeRefiner: KotlinTypeRefiner) : NewKotlinTypeChecker {
|
||||
|
||||
override fun isSubtypeOf(subtype: KotlinType, supertype: KotlinType): Boolean =
|
||||
ClassicTypeCheckerContext(true).isSubtypeOf(subtype.unwrap(), supertype.unwrap()) // todo fix flag errorTypeEqualsToAnything
|
||||
ClassicTypeCheckerContext(true, kotlinTypeRefiner = kotlinTypeRefiner)
|
||||
.isSubtypeOf(subtype.unwrap(), supertype.unwrap()) // todo fix flag errorTypeEqualsToAnything
|
||||
|
||||
override fun equalTypes(a: KotlinType, b: KotlinType): Boolean =
|
||||
ClassicTypeCheckerContext(false).equalTypes(a.unwrap(), b.unwrap())
|
||||
ClassicTypeCheckerContext(false, kotlinTypeRefiner = kotlinTypeRefiner).equalTypes(a.unwrap(), b.unwrap())
|
||||
|
||||
fun ClassicTypeCheckerContext.equalTypes(a: UnwrappedType, b: UnwrappedType): Boolean {
|
||||
return AbstractTypeChecker.equalTypes(this as AbstractTypeCheckerContext, a, b)
|
||||
|
||||
@@ -25,6 +25,10 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
|
||||
return type
|
||||
}
|
||||
|
||||
open fun refineType(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
return type
|
||||
}
|
||||
|
||||
abstract val isErrorTypeEqualsToAnything: Boolean
|
||||
|
||||
protected var argumentsDepth = 0
|
||||
@@ -157,19 +161,21 @@ object AbstractTypeChecker {
|
||||
|
||||
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
|
||||
if (subType === superType) return true
|
||||
return context.completeIsSubTypeOf(context.prepareType(subType), context.prepareType(superType))
|
||||
return with(context) { completeIsSubTypeOf(prepareType(refineType(subType)), prepareType(refineType(superType))) }
|
||||
}
|
||||
|
||||
fun equalTypes(context: AbstractTypeCheckerContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean = with(context) {
|
||||
if (a === b) return true
|
||||
|
||||
if (isCommonDenotableType(a) && isCommonDenotableType(b)) {
|
||||
val simpleA = a.lowerBoundIfFlexible()
|
||||
if (!areEqualTypeConstructors(a.typeConstructor(), b.typeConstructor())) return false
|
||||
val refinedA = refineType(a)
|
||||
val refinedB = refineType(b)
|
||||
val simpleA = refinedA.lowerBoundIfFlexible()
|
||||
if (!areEqualTypeConstructors(refinedA.typeConstructor(), refinedB.typeConstructor())) return false
|
||||
if (simpleA.argumentsCount() == 0) {
|
||||
if (a.hasFlexibleNullability() || b.hasFlexibleNullability()) return true
|
||||
if (refinedA.hasFlexibleNullability() || refinedB.hasFlexibleNullability()) return true
|
||||
|
||||
return simpleA.isMarkedNullable() == b.lowerBoundIfFlexible().isMarkedNullable()
|
||||
return simpleA.isMarkedNullable() == refinedB.lowerBoundIfFlexible().isMarkedNullable()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user