From 01ad9c47c8f7447344d64dc21bc2c8437bb0474d Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 21 Aug 2019 16:18:02 +0300 Subject: [PATCH] [NI] Fix subtyping between integer literal types and intersection ones Consider a call like `select(1, "")`, the resulting type for it is Comparable & 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 & 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 --- .../org/jetbrains/kotlin/types/AbstractTypeChecker.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt b/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt index 74c7cacb942..cc7f3739be2 100644 --- a/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt +++ b/core/type-system/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt @@ -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 } }