Make type-system KotlinType-independent

- Port NewKotlinTypeChecker.equalTypes
- Decouple new-type transform from isSubtypeOf
- Port isSubtypeForSameConstructor
- Port checkSubtypeForSpecialCases
- Port isSubTypeOf without internals
- Port anySupertype
- Port isSubtypeForSameConstructor, findCorrespondingSupertypes
- Port isSubtypeOfForSingleClassifierType
- Port NullabilityChecker
- Reorder checks for performance
This commit is contained in:
Simon Ogorodnik
2019-01-22 20:54:01 +03:00
parent d210e8bad0
commit 4882627712
25 changed files with 1049 additions and 582 deletions
@@ -40,9 +40,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.checker.TypeCheckerContext
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.typeUtil.*
import javax.inject.Inject
@@ -277,9 +278,11 @@ class CoroutineInferenceSupport(
private class CoroutineTypeCheckerContext(
private val allowOnlyTrivialConstraints: Boolean
) : TypeCheckerContext(errorTypeEqualsToAnything = true) {
) : ClassicTypeCheckerContext(errorTypeEqualsToAnything = true) {
override fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? {
override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
require(subType is UnwrappedType)
require(superType is UnwrappedType)
val typeTemplate = subType as? TypeTemplate ?: superType as? TypeTemplate
typeTemplate?.coroutineInferenceData?.addConstraint(subType, superType, allowOnlyTrivialConstraints)
return null
@@ -154,7 +154,7 @@ object NewCommonSuperTypeCalculator {
nullable = false
)
val typeCheckerContext = TypeCheckerContext(false)
val typeCheckerContext = ClassicTypeCheckerContext(false)
/**
* Sometimes one type can have several supertypes with given type constructor, suppose A <: List<Int> and A <: List<Double>.
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.CaptureStatus
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -22,9 +22,9 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.LOWER
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.UPPER
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.CaptureStatus
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
@@ -11,10 +11,13 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasNoInferAnnotation
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinTypeFactory.flexibleType
import org.jetbrains.kotlin.types.checker.*
import org.jetbrains.kotlin.types.model.CapturedTypeMarker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.contains
abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorTypeEqualsToAnything = true, allowedTypeVariable = false) {
abstract class TypeCheckerContextForConstraintSystem : ClassicTypeCheckerContext(errorTypeEqualsToAnything = true, allowedTypeVariable = false) {
abstract fun isMyTypeVariable(type: SimpleType): Boolean
@@ -23,7 +26,13 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType)
override fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when {
override fun getLowerCapturedTypePolicy(subType: SimpleTypeMarker, superType: CapturedTypeMarker): LowerCapturedTypePolicy {
require(subType is SimpleType)
require(superType is NewCapturedType)
return getLowerCapturedTypePolicy(subType, superType)
}
private fun getLowerCapturedTypePolicy(subType: SimpleType, superType: NewCapturedType) = when {
isMyTypeVariable(subType) -> LowerCapturedTypePolicy.SKIP_LOWER
subType.contains { it.anyBound(this::isMyTypeVariable) } -> LowerCapturedTypePolicy.CHECK_ONLY_LOWER
else -> LowerCapturedTypePolicy.CHECK_SUBTYPE_AND_LOWER
@@ -35,7 +44,9 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
* then we can get wrong result.
* override val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.TAKE_FIRST_FOR_SUBTYPING
*/
override final fun addSubtypeConstraint(subType: UnwrappedType, superType: UnwrappedType): Boolean? {
final override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean? {
require(subType is UnwrappedType)
require(superType is UnwrappedType)
val hasNoInfer = subType.isTypeVariableWithNoInfer() || superType.isTypeVariableWithNoInfer()
if (hasNoInfer) return true
@@ -199,7 +210,7 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
val notTypeVariables = subIntersectionTypes.filterNot(this::isMyTypeVariable)
// todo: may be we can do better then that.
if (notTypeVariables.isNotEmpty() && NewKotlinTypeChecker.isSubtypeOf(intersectTypes(notTypeVariables), superType)) {
if (notTypeVariables.isNotEmpty() && NewKotlinTypeChecker.isSubtypeOf(intersectTypes(notTypeVariables) as KotlinType, superType)) {
return true
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeConstructorSubstitution
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
import org.jetbrains.kotlin.types.checker.TypeCheckerContext
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerContext
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.keysToMap
@@ -302,7 +302,7 @@ object ExpectedActualResolver {
if (b == null) return false
with(NewKotlinTypeChecker) {
val context = object : TypeCheckerContext(false) {
val context = object : ClassicTypeCheckerContext(false) {
override fun areEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean {
return isExpectedClassAndActualTypeAlias(a, b, platformModule) ||
isExpectedClassAndActualTypeAlias(b, a, platformModule) ||
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.*
import org.jetbrains.kotlin.types.checker.*
import org.jetbrains.kotlin.types.checker.CaptureStatus.*
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.types.model.CaptureStatus.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.types.typeUtil.isNothing