diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt index 6c67e27e710..ed0a0bce2db 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/KtSymbolByFirBuilder.kt @@ -436,7 +436,8 @@ internal class KtSymbolByFirBuilder private constructor( is ConeIntersectionType -> KtFirIntersectionType(coneType, token, this@KtSymbolByFirBuilder) is ConeDefinitelyNotNullType -> KtFirDefinitelyNotNullType(coneType, token, this@KtSymbolByFirBuilder) is ConeCapturedType -> KtFirCapturedType(coneType, token, this@KtSymbolByFirBuilder) - is ConeIntegerLiteralType -> KtFirIntegerLiteralType(coneType, token, this@KtSymbolByFirBuilder) + is ConeIntegerLiteralConstantType -> KtFirIntegerLiteralType(coneType, token, this@KtSymbolByFirBuilder) + is ConeIntegerConstantOperatorType -> buildKtType(coneType.getApproximatedType()) is ConeStubTypeForChainInference -> { // TODO this is a temporary hack to prevent FIR IDE from crashing on builder inference, see KT-50916 val typeVariable = coneType.constructor.variable as? ConeTypeParameterBasedTypeVariable diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt index a2d6681eaab..9700b9c5115 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/types/FirKtType.kt @@ -230,7 +230,7 @@ internal class KtFirIntersectionType( } internal class KtFirIntegerLiteralType( - override val coneType: ConeIntegerLiteralType, + override val coneType: ConeIntegerLiteralConstantType, override val token: ValidityToken, private val builder: KtSymbolByFirBuilder, ) : KtIntegerLiteralType(), KtFirType { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt index b53c29cd3f9..f06bbf1f840 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/ConeTypeCompatibilityChecker.kt @@ -255,7 +255,8 @@ object ConeTypeCompatibilityChecker { is ConeIntersectionType -> intersectedTypes.flatMap { it.collectUpperBounds() }.toSet() is ConeFlexibleType -> upperBound.collectUpperBounds() is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectUpperBounds() }?.toSet().orEmpty() - is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here") + is ConeIntegerConstantOperatorType -> setOf(getApproximatedType()) + is ConeStubType, is ConeIntegerLiteralConstantType -> throw IllegalStateException("$this should not reach here") } } @@ -278,7 +279,8 @@ object ConeTypeCompatibilityChecker { is ConeIntersectionType -> intersectedTypes.flatMap { it.collectLowerBounds() }.toSet() is ConeFlexibleType -> lowerBound.collectLowerBounds() is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectLowerBounds() }?.toSet().orEmpty() - is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here") + is ConeIntegerConstantOperatorType -> setOf(getApproximatedType()) + is ConeStubType, is ConeIntegerLiteralConstantType -> throw IllegalStateException("$this should not reach here") } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt index a722837e845..fe48d26c90e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt @@ -93,10 +93,14 @@ interface FirDeclarationPresenter { append(it.lookupTag.name) append(it.nullability.suffix) } - is ConeIntegerLiteralType -> { + is ConeIntegerLiteralConstantType -> { append(it.value) append(it.nullability.suffix) } + is ConeIntegerConstantOperatorType -> { + append("IOT") + append(it.nullability.suffix) + } is ConeFlexibleType, is ConeIntersectionType, is ConeStubType -> { diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralType.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralType.kt index 79a09769f1f..4090bdc8390 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralType.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralType.kt @@ -7,31 +7,45 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.types.model.TypeConstructorMarker -abstract class ConeIntegerLiteralType( - val value: Long, +sealed class ConeIntegerLiteralType( val isUnsigned: Boolean, - override val nullability: ConeNullability + final override val nullability: ConeNullability ) : ConeSimpleKotlinType(), TypeConstructorMarker { abstract val possibleTypes: Collection abstract val supertypes: List - override val typeArguments: Array = emptyArray() + final override val typeArguments: Array = emptyArray() + final override val attributes: ConeAttributes get() = ConeAttributes.Empty abstract fun getApproximatedType(expectedType: ConeKotlinType? = null): ConeClassLikeType - override fun equals(other: Any?): Boolean { + final override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as ConeIntegerLiteralType + if (isUnsigned != other.isUnsigned) return false if (possibleTypes != other.possibleTypes) return false if (nullability != other.nullability) return false return true } - override fun hashCode(): Int { + final override fun hashCode(): Int { return 31 * possibleTypes.hashCode() + nullability.hashCode() } + + companion object } + +abstract class ConeIntegerLiteralConstantType( + val value: Long, + isUnsigned: Boolean, + nullability: ConeNullability +) : ConeIntegerLiteralType(isUnsigned, nullability) + +abstract class ConeIntegerConstantOperatorType( + isUnsigned: Boolean, + nullability: ConeNullability +) : ConeIntegerLiteralType(isUnsigned, nullability) diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt index 5b61e592072..e771c4cb6a1 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/TypeRenderer.kt @@ -49,7 +49,8 @@ fun ConeKotlinType.render(): String { is ConeStubTypeForChainInference -> "${renderAttributes()}Stub (chain inference): ${constructor.variable}" is ConeStubTypeForSyntheticFixation -> "${renderAttributes()}Stub (fixation): ${constructor.variable}" is ConeStubType -> "${renderAttributes()}Stub (subtyping): ${constructor.variable}" - is ConeIntegerLiteralType -> "${renderAttributes()}ILT: $value" + is ConeIntegerLiteralConstantType -> "${renderAttributes()}ILT: $value" + is ConeIntegerConstantOperatorType -> "${renderAttributes()}IOT" } + nullabilitySuffix } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt index a8a9742c6fc..7ead263c8d3 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt @@ -397,7 +397,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo } override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List): SimpleTypeMarker? { - return ConeIntegerLiteralTypeImpl.findCommonSuperType(explicitSupertypes) + return ConeIntegerLiteralType.findCommonSuperType(explicitSupertypes) } override fun unionTypeAttributes(types: List): List { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 6e86bdcbaa2..9b2eaab3b21 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -175,7 +175,8 @@ fun T.withNullability( ConeNullability.NULLABLE -> original.withNullability(nullability, typeContext) ConeNullability.UNKNOWN -> original.withNullability(nullability, typeContext) } - is ConeIntegerLiteralTypeImpl -> ConeIntegerLiteralTypeImpl(value, possibleTypes, isUnsigned, nullability) + is ConeIntegerLiteralConstantType -> ConeIntegerLiteralConstantTypeImpl(value, possibleTypes, isUnsigned, nullability) + is ConeIntegerConstantOperatorType -> ConeIntegerConstantOperatorTypeImpl(isUnsigned, nullability) else -> error("sealed: ${this::class}") } as T } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 1cd5896a55d..b329f333a4f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -906,7 +906,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform val type = when (val kind = constExpression.kind) { ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> { - val expressionType = ConeIntegerLiteralTypeImpl.create( + val expressionType = ConeIntegerLiteralConstantTypeImpl.create( constExpression.value as Long, isUnsigned = kind == ConstantValueKind.UnsignedIntegerLiteral ) @@ -918,7 +918,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform expressionType } expectedTypeRef != null -> { - require(expressionType is ConeIntegerLiteralTypeImpl) + require(expressionType is ConeIntegerLiteralConstantTypeImpl) val coneType = expectedTypeRef.coneTypeSafe()?.fullyExpandedType(session) val approximatedType= expressionType.getApproximatedType(coneType) constExpression.replaceKind(approximatedType.toConstKind() as ConstantValueKind) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt index 3a64411a524..0ef2fce34fc 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeIntegerLiteralTypeImpl.kt @@ -9,35 +9,28 @@ import org.jetbrains.kotlin.fir.isLong import org.jetbrains.kotlin.fir.isULong import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeExtensions.approximateIntegerLiteralBounds +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeExtensions.createClassLikeType +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeExtensions.createSupertypeList +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeExtensions.getApproximatedTypeImpl +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralTypeExtensions.withNullability import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.model.SimpleTypeMarker -class ConeIntegerLiteralTypeImpl( +class ConeIntegerLiteralConstantTypeImpl( value: Long, override val possibleTypes: Collection, isUnsigned: Boolean, nullability: ConeNullability -) : ConeIntegerLiteralType(value, isUnsigned, nullability) { - override val attributes: ConeAttributes - get() = ConeAttributes.Empty - +) : ConeIntegerLiteralConstantType(value, isUnsigned, nullability) { override val supertypes: List by lazy { - listOf( - createType(StandardClassIds.Number), - ConeClassLikeTypeImpl(COMPARABLE_TAG, arrayOf(ConeKotlinTypeProjectionIn(this)), false) - ) + createSupertypeList(this) } override fun getApproximatedType(expectedType: ConeKotlinType?): ConeClassLikeType { - val expectedTypeForApproximation = (expectedType?.lowerBoundIfFlexible() as? ConeClassLikeType) - ?.withNullability(ConeNullability.NOT_NULL) - val approximatedType = when (expectedTypeForApproximation) { - null, !in possibleTypes -> possibleTypes.first() - else -> expectedTypeForApproximation - } - return approximatedType.withNullability(nullability) + return getApproximatedTypeImpl(expectedType) } @OptIn(ExperimentalUnsignedTypes::class) @@ -81,7 +74,7 @@ class ConeIntegerLiteralTypeImpl( } } } else { - ConeIntegerLiteralTypeImpl(value, possibleTypes, isUnsigned, nullability) + ConeIntegerLiteralConstantTypeImpl(value, possibleTypes, isUnsigned, nullability) } } @@ -96,61 +89,42 @@ class ConeIntegerLiteralTypeImpl( private val UBYTE_RANGE = UByte.MIN_VALUE.toLong()..UByte.MAX_VALUE.toLong() private val USHORT_RANGE = UShort.MIN_VALUE.toLong()..UShort.MAX_VALUE.toLong() private val UINT_RANGE = UInt.MIN_VALUE.toLong()..UInt.MAX_VALUE.toLong() - - private val COMPARABLE_TAG = ConeClassLikeLookupTagImpl(StandardClassIds.Comparable) - - fun findCommonSuperType(types: Collection): SimpleTypeMarker? { - return findCommonSuperTypeOrIntersectionType(types, Mode.COMMON_SUPER_TYPE) - } - - fun findIntersectionType(types: Collection): SimpleTypeMarker? { - return findCommonSuperTypeOrIntersectionType(types, Mode.INTERSECTION_TYPE) - } - - private enum class Mode { - COMMON_SUPER_TYPE, INTERSECTION_TYPE - } - - /** - * intersection(ILT(types), PrimitiveType) = commonSuperType(ILT(types), PrimitiveType) = - * PrimitiveType in types -> PrimitiveType - * PrimitiveType !in types -> null - * - * intersection(ILT(types_1), ILT(types_2)) = ILT(types_1 union types_2) - * - * commonSuperType(ILT(types_1), ILT(types_2)) = ILT(types_1 intersect types_2) - */ - private fun findCommonSuperTypeOrIntersectionType(types: Collection, mode: Mode): SimpleTypeMarker? { - if (types.isEmpty()) return null - @Suppress("UNCHECKED_CAST") - return types.reduce { left: SimpleTypeMarker?, right: SimpleTypeMarker? -> fold(left, right, mode) } - } - - private fun fold(left: SimpleTypeMarker?, right: SimpleTypeMarker?, mode: Mode): SimpleTypeMarker? { - if (left == null || right == null) return null - return when { - left is ConeIntegerLiteralType && right is ConeIntegerLiteralType -> - fold(left, right, mode) - - left is ConeIntegerLiteralType -> fold(left, right) - right is ConeIntegerLiteralType -> fold(right, left) - else -> null - } - } - - private fun fold(left: ConeIntegerLiteralType, right: ConeIntegerLiteralType, mode: Mode): ConeIntegerLiteralType { - val possibleTypes = when (mode) { - Mode.COMMON_SUPER_TYPE -> left.possibleTypes intersect right.possibleTypes - Mode.INTERSECTION_TYPE -> left.possibleTypes union right.possibleTypes - } - return ConeIntegerLiteralTypeImpl(left.value, possibleTypes, left.isUnsigned, left.nullability) - } - - private fun fold(left: ConeIntegerLiteralType, right: SimpleTypeMarker): SimpleTypeMarker? = - if (right in left.possibleTypes) right else null } } +class ConeIntegerConstantOperatorTypeImpl( + isUnsigned: Boolean, + nullability: ConeNullability +) : ConeIntegerConstantOperatorType(isUnsigned, nullability) { + override val possibleTypes: Collection = when (isUnsigned) { + false -> setOf( + createClassLikeType(StandardClassIds.Int), + createClassLikeType(StandardClassIds.Long), + ) + true -> setOf( + createClassLikeType(StandardClassIds.UInt), + createClassLikeType(StandardClassIds.ULong), + ) + } + + override val supertypes: List by lazy { + createSupertypeList(this) + } + + override fun getApproximatedType(expectedType: ConeKotlinType?): ConeClassLikeType { + return getApproximatedTypeImpl(expectedType) + } +} + +/** + * This methods detects common super type only for special rules for integer literal types + * If it returns null then CST will be found by regular rules using real supertypes + * of integer literal types + */ +fun ConeIntegerLiteralType.Companion.findCommonSuperType(types: Collection): SimpleTypeMarker? { + return ConeIntegerLiteralTypeExtensions.findCommonSuperType(types) +} + fun ConeKotlinType.approximateIntegerLiteralType(expectedType: ConeKotlinType? = null): ConeKotlinType { return when (this) { is ConeIntegerLiteralType -> getApproximatedType(expectedType) @@ -159,26 +133,98 @@ fun ConeKotlinType.approximateIntegerLiteralType(expectedType: ConeKotlinType? = } } -private fun ConeFlexibleType.approximateIntegerLiteralBounds(expectedType: ConeKotlinType? = null): ConeFlexibleType { - val newLowerBound = lowerBound.approximateIntegerLiteralType(expectedType) - val newUpperBound = upperBound.approximateIntegerLiteralType(expectedType) +private object ConeIntegerLiteralTypeExtensions { + private val COMPARABLE_TAG = ConeClassLikeLookupTagImpl(StandardClassIds.Comparable) - if (newLowerBound !== lowerBound || newUpperBound !== upperBound) { - return ConeFlexibleType( - newLowerBound.lowerBoundIfFlexible(), - newUpperBound.upperBoundIfFlexible() + fun createSupertypeList(type: ConeIntegerLiteralType): List { + return listOf( + createClassLikeType(StandardClassIds.Number), + ConeClassLikeTypeImpl(COMPARABLE_TAG, arrayOf(ConeKotlinTypeProjectionIn(type)), false) ) } - return this -} + fun createClassLikeType(classId: ClassId): ConeClassLikeType { + return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(classId), emptyArray(), false) + } -private fun ConeClassLikeType.withNullability(nullability: ConeNullability): ConeClassLikeType { - if (nullability == this.nullability) return this + fun ConeIntegerLiteralType.getApproximatedTypeImpl(expectedType: ConeKotlinType?): ConeClassLikeType { + val expectedTypeForApproximation = (expectedType?.lowerBoundIfFlexible() as? ConeClassLikeType) + ?.withNullability(ConeNullability.NOT_NULL) + val approximatedType = when (expectedTypeForApproximation) { + null, !in possibleTypes -> possibleTypes.first() + else -> expectedTypeForApproximation + } + return approximatedType.withNullability(nullability) + } - return when (this) { - is ConeErrorType -> this - is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable) - else -> error("sealed") + + fun findCommonSuperType(types: Collection): SimpleTypeMarker? { + if (types.isEmpty()) return null + @Suppress("UNCHECKED_CAST") + return types.reduce { left: SimpleTypeMarker?, right: SimpleTypeMarker? -> commonSuperType(left, right) } + } + + private fun commonSuperType(left: SimpleTypeMarker?, right: SimpleTypeMarker?): SimpleTypeMarker? { + if (left == null || right == null) return null + + return when { + left is ConeIntegerLiteralType && right !is ConeIntegerLiteralType -> { + commonSuperTypeBetweenIntegerTypeAndRegularType(left, right) + } + + right is ConeIntegerLiteralType && left !is ConeIntegerLiteralType -> { + commonSuperTypeBetweenIntegerTypeAndRegularType(right, left) + } + + left is ConeIntegerLiteralConstantType && right is ConeIntegerLiteralConstantType -> { + commonSuperTypeBetweenTwoConstantTypes(left, right) + } + + left is ConeIntegerConstantOperatorType -> left + right is ConeIntegerConstantOperatorType -> right + else -> null + } + } + + private fun commonSuperTypeBetweenIntegerTypeAndRegularType( + integerLiteralType: ConeIntegerLiteralType, + regularType: SimpleTypeMarker + ): SimpleTypeMarker? { + return when (regularType) { + in integerLiteralType.possibleTypes -> regularType + else -> null + } + } + + private fun commonSuperTypeBetweenTwoConstantTypes( + left: ConeIntegerLiteralConstantType, + right: ConeIntegerLiteralConstantType + ): ConeIntegerLiteralConstantType { + val possibleTypes = left.possibleTypes intersect right.possibleTypes + return ConeIntegerLiteralConstantTypeImpl(left.value, possibleTypes, left.isUnsigned, left.nullability) + } + + fun ConeFlexibleType.approximateIntegerLiteralBounds(expectedType: ConeKotlinType? = null): ConeFlexibleType { + val newLowerBound = lowerBound.approximateIntegerLiteralType(expectedType) + val newUpperBound = upperBound.approximateIntegerLiteralType(expectedType) + + if (newLowerBound !== lowerBound || newUpperBound !== upperBound) { + return ConeFlexibleType( + newLowerBound.lowerBoundIfFlexible(), + newUpperBound.upperBoundIfFlexible() + ) + } + + return this + } + + fun ConeClassLikeType.withNullability(nullability: ConeNullability): ConeClassLikeType { + if (nullability == this.nullability) return this + + return when (this) { + is ConeErrorType -> this + is ConeClassLikeTypeImpl -> ConeClassLikeTypeImpl(lookupTag, typeArguments, nullability.isNullable) + else -> error("sealed") + } } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt index 410b25ae815..df7c4369160 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/ConeKotlinTypeComparator.kt @@ -8,14 +8,15 @@ package org.jetbrains.kotlin.fir.types object ConeKotlinTypeComparator : Comparator { private val ConeKotlinType.priority : Int get() = when (this) { - is ConeErrorType -> 8 - is ConeLookupTagBasedType -> 7 - is ConeFlexibleType -> 6 - is ConeCapturedType -> 5 - is ConeDefinitelyNotNullType -> 4 - is ConeIntersectionType -> 3 - is ConeStubType -> 2 - is ConeIntegerLiteralType -> 1 + is ConeErrorType -> 9 + is ConeLookupTagBasedType -> 8 + is ConeFlexibleType -> 7 + is ConeCapturedType -> 6 + is ConeDefinitelyNotNullType -> 5 + is ConeIntersectionType -> 4 + is ConeStubType -> 3 + is ConeIntegerLiteralConstantType -> 2 + is ConeIntegerConstantOperatorType -> 1 else -> 0 } @@ -151,8 +152,8 @@ object ConeKotlinTypeComparator : Comparator { } return compare(a.nullability, b.nullability) } - is ConeIntegerLiteralType -> { - require(b is ConeIntegerLiteralType) { + is ConeIntegerLiteralConstantType -> { + require(b is ConeIntegerLiteralConstantType) { "priority is inconsistent: ${a.render()} v.s. ${b.render()}" } val valueDiff = a.value - b.value @@ -166,6 +167,9 @@ object ConeKotlinTypeComparator : Comparator { // Can't compare individual types from each side, since their orders are not guaranteed. return a.hashCode() - b.hashCode() } + is ConeIntegerConstantOperatorType -> { + return compare(a.nullability, b.nullability) + } else -> error("Unsupported type comparison: ${a.render()} v.s. ${b.render()}") } diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/RenderingForDebugInfo.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/RenderingForDebugInfo.kt index 7b5f96c129f..6867da43254 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/RenderingForDebugInfo.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/RenderingForDebugInfo.kt @@ -40,7 +40,8 @@ fun ConeKotlinType.renderForDebugInfo(): String { ) { it.renderForDebugInfo() } } is ConeStubType -> "Stub: ${constructor.variable}" - is ConeIntegerLiteralType -> "ILT: $value" + is ConeIntegerLiteralConstantType -> "ILT: $value" + is ConeIntegerConstantOperatorType -> "IOT" } + nullabilitySuffix }