[NI] Fix special case of captured type handling in subtyping

Given the subtyping constraint
  X <: CapturedType(in Y)
we should check only
  X <: Y
if X contains type variables.
This commit is contained in:
Dmitry Petrov
2017-06-07 15:11:04 +03:00
committed by Mikhail Zarechenskiy
parent 26cc08be65
commit 9fa3bce73a
3 changed files with 11 additions and 9 deletions
@@ -29,8 +29,8 @@ abstract class TypeCheckerContextForConstraintSystem : TypeCheckerContext(errorT
abstract fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType) abstract fun addUpperConstraint(typeVariable: TypeConstructor, superType: UnwrappedType)
abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType) abstract fun addLowerConstraint(typeVariable: TypeConstructor, subType: UnwrappedType)
override fun allowSubtypeViaLowerTypeForCapturedType(subType: SimpleType, superType: NewCapturedType) = override fun shouldCheckOnlyLowerBoundForCapturedType(subType: SimpleType, superType: NewCapturedType) =
!subType.contains { it.anyBound(this::isMyTypeVariable) } subType.contains { it.anyBound(this::isMyTypeVariable) }
/** /**
* todo: possible we should override this method, because otherwise OR in subtyping transformed to AND in constraint system * todo: possible we should override this method, because otherwise OR in subtyping transformed to AND in constraint system
@@ -159,12 +159,14 @@ object NewKotlinTypeChecker : KotlinTypeChecker {
return StrictEqualityTypeChecker.strictEqualTypes(subType.makeNullableAsSpecified(false), superType.makeNullableAsSpecified(false)) return StrictEqualityTypeChecker.strictEqualTypes(subType.makeNullableAsSpecified(false), superType.makeNullableAsSpecified(false))
} }
if (superType is NewCapturedType && if (superType is NewCapturedType && superType.lowerType != null) {
superType.lowerType != null && val subtypeOfLowerType = isSubtypeOf(subType, superType.lowerType)
allowSubtypeViaLowerTypeForCapturedType(subType, superType) && if (shouldCheckOnlyLowerBoundForCapturedType(subType, superType)) {
isSubtypeOf(subType, superType.lowerType)) return subtypeOfLowerType
{ }
return true else if (subtypeOfLowerType) {
return true
}
} }
(superType.constructor as? IntersectionTypeConstructor)?.let { (superType.constructor as? IntersectionTypeConstructor)?.let {
@@ -33,7 +33,7 @@ open class TypeCheckerContext(val errorTypeEqualsToAnything: Boolean, val allowe
return a == b return a == b
} }
open fun allowSubtypeViaLowerTypeForCapturedType(subType: SimpleType, superType: NewCapturedType): Boolean = true open fun shouldCheckOnlyLowerBoundForCapturedType(subType: SimpleType, superType: NewCapturedType): Boolean = false
open val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.INTERSECT_ARGUMENTS_AND_CHECK_AGAIN open val sameConstructorPolicy get() = SeveralSupertypesWithSameConstructorPolicy.INTERSECT_ARGUMENTS_AND_CHECK_AGAIN
internal inline fun <T> runWithArgumentsSettings(subArgument: UnwrappedType, f: TypeCheckerContext.() -> T): T { internal inline fun <T> runWithArgumentsSettings(subArgument: UnwrappedType, f: TypeCheckerContext.() -> T): T {