[NI] Fix subtyping between integer literal types and intersection ones

Consider a call like `select(1, "")`, the resulting type for it is
 Comparable<Int & String> & Serializable.

 After variable fixation, the compiler incorporates this type into the
 constraint system to check for a contradiction, so it checks
 applicability of argument to the resulting type.

 In other words, for the above call it checks is
 `Comparable<Int & String> & Serializable` subtype of `IntegerLiteralType`?
 Which ends up in checking is `IntegerLiteralType` subtype of `Int & String`.

 Before this commit, such check was leading to the false result, but
 because of losing diagnostic (which was fixed in the previous commit:
 29f591b1), there was no error
This commit is contained in:
Mikhail Zarechenskiy
2019-08-21 16:18:02 +03:00
parent e0fb586aaf
commit 01ad9c47c8
@@ -210,8 +210,10 @@ object AbstractTypeChecker {
private fun AbstractTypeCheckerContext.checkSubtypeForIntegerLiteralType(subType: SimpleTypeMarker, superType: SimpleTypeMarker): Boolean? {
if (!subType.isIntegerLiteralType() && !superType.isIntegerLiteralType()) return null
fun typeInIntegerLiteralType(integerLiteralType: SimpleTypeMarker, type: SimpleTypeMarker): Boolean =
integerLiteralType.possibleIntegerTypes().any { it.typeConstructor() == type.typeConstructor() }
fun typeInIntegerLiteralType(integerLiteralType: SimpleTypeMarker, type: SimpleTypeMarker, checkSupertypes: Boolean): Boolean =
integerLiteralType.possibleIntegerTypes().any { possibleType ->
(possibleType.typeConstructor() == type.typeConstructor()) || (checkSupertypes && isSubtypeOf(this, type, possibleType))
}
when {
subType.isIntegerLiteralType() && superType.isIntegerLiteralType() -> {
@@ -219,13 +221,14 @@ object AbstractTypeChecker {
}
subType.isIntegerLiteralType() -> {
if (typeInIntegerLiteralType(subType, superType)) {
if (typeInIntegerLiteralType(subType, superType, checkSupertypes = false)) {
return true
}
}
superType.isIntegerLiteralType() -> {
if (typeInIntegerLiteralType(superType, subType)) {
// Here we also have to check supertypes for intersection types: { Int & String } <: IntegerLiteralTypes
if (typeInIntegerLiteralType(superType, subType, checkSupertypes = true)) {
return true
}
}