[NI] Improve CST algorithm to handle non-fixed variables

#KT-32456 Fixed
 #KT-32423 Fixed
 #KT-32818 Fixed
 #KT-33197 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-08-28 01:23:18 +03:00
parent ba6648d535
commit ca8da22569
41 changed files with 605 additions and 81 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.types.refinement.TypeRefinement
open class ClassicTypeCheckerContext(
val errorTypeEqualsToAnything: Boolean,
val stubTypeEqualsToAnything: Boolean = true,
val allowedTypeVariable: Boolean = true,
val kotlinTypeRefiner: KotlinTypeRefiner = KotlinTypeRefiner.Default
) : ClassicTypeSystemContext, AbstractTypeCheckerContext() {
@@ -43,6 +44,9 @@ open class ClassicTypeCheckerContext(
override val isErrorTypeEqualsToAnything: Boolean
get() = errorTypeEqualsToAnything
override val isStubTypeEqualsToAnything: Boolean
get() = stubTypeEqualsToAnything
override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean {
require(a is TypeConstructor, a::errorMessage)
require(b is TypeConstructor, b::errorMessage)
@@ -321,8 +321,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
}
override fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext {
return ClassicTypeCheckerContext(errorTypesEqualToAnything)
override fun newBaseTypeCheckerContext(
errorTypesEqualToAnything: Boolean,
stubTypesEqualToAnything: Boolean
): AbstractTypeCheckerContext {
return ClassicTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything)
}
override fun nullableNothingType(): SimpleTypeMarker {
@@ -148,7 +148,7 @@ object NullabilityChecker {
fun isSubtypeOfAny(type: UnwrappedType): Boolean =
SimpleClassicTypeSystemContext
.newBaseTypeCheckerContext(false)
.newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
.hasNotNullSupertype(type.lowerIfFlexible(), SupertypesPolicy.LowerIfFlexible)
}
@@ -31,6 +31,8 @@ abstract class AbstractTypeCheckerContext : TypeSystemContext {
abstract val isErrorTypeEqualsToAnything: Boolean
abstract val isStubTypeEqualsToAnything: Boolean
protected var argumentsDepth = 0
@@ -151,12 +153,22 @@ object AbstractTypeChecker {
@JvmField
var RUN_SLOW_ASSERTIONS = false
fun isSubtypeOf(context: TypeCheckerProviderContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
return AbstractTypeChecker.isSubtypeOf(context.newBaseTypeCheckerContext(true), subType, superType)
fun isSubtypeOf(
context: TypeCheckerProviderContext,
subType: KotlinTypeMarker,
superType: KotlinTypeMarker,
stubTypesEqualToAnything: Boolean = true
): Boolean {
return AbstractTypeChecker.isSubtypeOf(context.newBaseTypeCheckerContext(true, stubTypesEqualToAnything), subType, superType)
}
fun equalTypes(context: TypeCheckerProviderContext, a: KotlinTypeMarker, b: KotlinTypeMarker): Boolean {
return AbstractTypeChecker.equalTypes(context.newBaseTypeCheckerContext(false), a, b)
fun equalTypes(
context: TypeCheckerProviderContext,
a: KotlinTypeMarker,
b: KotlinTypeMarker,
stubTypesEqualToAnything: Boolean = true
): Boolean {
return AbstractTypeChecker.equalTypes(context.newBaseTypeCheckerContext(false, stubTypesEqualToAnything), a, b)
}
fun isSubtypeOf(context: AbstractTypeCheckerContext, subType: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean {
@@ -358,7 +370,7 @@ object AbstractTypeChecker {
)
}
if (subType.isStubType() || superType.isStubType()) return true
if (subType.isStubType() || superType.isStubType()) return isStubTypeEqualsToAnything
val superTypeCaptured = superType.asCapturedType()
val lowerType = superTypeCaptured?.lowerType()
@@ -482,7 +494,13 @@ object AbstractNullabilityChecker {
context.runIsPossibleSubtype(subType, superType)
fun isSubtypeOfAny(context: TypeCheckerProviderContext, type: KotlinTypeMarker): Boolean =
AbstractNullabilityChecker.isSubtypeOfAny(context.newBaseTypeCheckerContext(false), type)
AbstractNullabilityChecker.isSubtypeOfAny(
context.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = true
),
type
)
fun isSubtypeOfAny(context: AbstractTypeCheckerContext, type: KotlinTypeMarker): Boolean =
with(context) {
@@ -540,12 +558,22 @@ object AbstractNullabilityChecker {
}
fun TypeCheckerProviderContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
newBaseTypeCheckerContext(false).hasPathByNotMarkedNullableNodes(start, end)
newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
.hasPathByNotMarkedNullableNodes(start, end)
fun AbstractTypeCheckerContext.hasPathByNotMarkedNullableNodes(start: SimpleTypeMarker, end: TypeConstructorMarker) =
anySupertype(start, {
it.isNothing() || (!it.isMarkedNullable() && isEqualTypeConstructors(it.typeConstructor(), end))
}) {
if (it.isMarkedNullable()) SupertypesPolicy.None else SupertypesPolicy.LowerIfFlexible
}
anySupertype(
start,
{ isApplicableAsEndNode(it, end) },
{ if (it.isMarkedNullable()) SupertypesPolicy.None else SupertypesPolicy.LowerIfFlexible }
)
private fun AbstractTypeCheckerContext.isApplicableAsEndNode(type: SimpleTypeMarker, end: TypeConstructorMarker): Boolean {
if (type.isNothing()) return true
if (type.isMarkedNullable()) return false
if (isStubTypeEqualsToAnything && type.isStubType()) return true
return isEqualTypeConstructors(type.typeConstructor(), end)
}
}
@@ -63,7 +63,10 @@ interface TypeSystemTypeFactoryContext {
interface TypeCheckerProviderContext {
fun newBaseTypeCheckerContext(errorTypesEqualToAnything: Boolean): AbstractTypeCheckerContext
fun newBaseTypeCheckerContext(
errorTypesEqualToAnything: Boolean,
stubTypesEqualToAnything: Boolean
): AbstractTypeCheckerContext
}
interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeFactoryContext, TypeCheckerProviderContext {
@@ -74,9 +77,12 @@ interface TypeSystemCommonSuperTypesContext : TypeSystemContext, TypeSystemTypeF
val isErrorTypeAllowed: Boolean
fun KotlinTypeMarker.anySuperTypeConstructor(predicate: (TypeConstructorMarker) -> Boolean) =
newBaseTypeCheckerContext(false).anySupertype(lowerBoundIfFlexible(), {
predicate(it.typeConstructor())
}, { AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible })
newBaseTypeCheckerContext(errorTypesEqualToAnything = false, stubTypesEqualToAnything = true)
.anySupertype(
lowerBoundIfFlexible(),
{ predicate(it.typeConstructor()) },
{ AbstractTypeCheckerContext.SupertypesPolicy.LowerIfFlexible }
)
fun KotlinTypeMarker.canHaveUndefinedNullability(): Boolean