[FIR] Introduce new kind of integer literal types for constant operator calls
This commit is contained in:
committed by
teamcity
parent
bb5217be72
commit
b980f5ab32
+2
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+4
-2
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -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 -> {
|
||||
|
||||
@@ -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<ConeClassLikeType>
|
||||
abstract val supertypes: List<ConeClassLikeType>
|
||||
|
||||
override val typeArguments: Array<out ConeTypeProjection> = emptyArray()
|
||||
final override val typeArguments: Array<out ConeTypeProjection> = 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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
}
|
||||
|
||||
override fun findCommonIntegerLiteralTypesSuperType(explicitSupertypes: List<SimpleTypeMarker>): SimpleTypeMarker? {
|
||||
return ConeIntegerLiteralTypeImpl.findCommonSuperType(explicitSupertypes)
|
||||
return ConeIntegerLiteralType.findCommonSuperType(explicitSupertypes)
|
||||
}
|
||||
|
||||
override fun unionTypeAttributes(types: List<KotlinTypeMarker>): List<AnnotationMarker> {
|
||||
|
||||
@@ -175,7 +175,8 @@ fun <T : ConeKotlinType> 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
|
||||
}
|
||||
|
||||
+2
-2
@@ -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<ConeKotlinType>()?.fullyExpandedType(session)
|
||||
val approximatedType= expressionType.getApproximatedType(coneType)
|
||||
constExpression.replaceKind(approximatedType.toConstKind() as ConstantValueKind<T>)
|
||||
|
||||
+130
-84
@@ -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<ConeClassLikeType>,
|
||||
isUnsigned: Boolean,
|
||||
nullability: ConeNullability
|
||||
) : ConeIntegerLiteralType(value, isUnsigned, nullability) {
|
||||
override val attributes: ConeAttributes
|
||||
get() = ConeAttributes.Empty
|
||||
|
||||
) : ConeIntegerLiteralConstantType(value, isUnsigned, nullability) {
|
||||
override val supertypes: List<ConeClassLikeType> 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>): SimpleTypeMarker? {
|
||||
return findCommonSuperTypeOrIntersectionType(types, Mode.COMMON_SUPER_TYPE)
|
||||
}
|
||||
|
||||
fun findIntersectionType(types: Collection<SimpleTypeMarker>): 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<SimpleTypeMarker>, 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<ConeClassLikeType> = when (isUnsigned) {
|
||||
false -> setOf(
|
||||
createClassLikeType(StandardClassIds.Int),
|
||||
createClassLikeType(StandardClassIds.Long),
|
||||
)
|
||||
true -> setOf(
|
||||
createClassLikeType(StandardClassIds.UInt),
|
||||
createClassLikeType(StandardClassIds.ULong),
|
||||
)
|
||||
}
|
||||
|
||||
override val supertypes: List<ConeClassLikeType> 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>): 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<ConeClassLikeType> {
|
||||
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>): 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.fir.types
|
||||
object ConeKotlinTypeComparator : Comparator<ConeKotlinType> {
|
||||
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<ConeKotlinType> {
|
||||
}
|
||||
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<ConeKotlinType> {
|
||||
// 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()}")
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user