[FIR] Don't create ILT for integer literal if its value don't fit to Int type
This commit is contained in:
committed by
teamcity
parent
10c38ba47c
commit
bb5217be72
@@ -175,7 +175,7 @@ fun <T : ConeKotlinType> T.withNullability(
|
|||||||
ConeNullability.NULLABLE -> original.withNullability(nullability, typeContext)
|
ConeNullability.NULLABLE -> original.withNullability(nullability, typeContext)
|
||||||
ConeNullability.UNKNOWN -> original.withNullability(nullability, typeContext)
|
ConeNullability.UNKNOWN -> original.withNullability(nullability, typeContext)
|
||||||
}
|
}
|
||||||
is ConeIntegerLiteralType -> ConeIntegerLiteralTypeImpl(value, isUnsigned, nullability)
|
is ConeIntegerLiteralTypeImpl -> ConeIntegerLiteralTypeImpl(value, possibleTypes, isUnsigned, nullability)
|
||||||
else -> error("sealed: ${this::class}")
|
else -> error("sealed: ${this::class}")
|
||||||
} as T
|
} as T
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-11
@@ -906,17 +906,27 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
|
|
||||||
val type = when (val kind = constExpression.kind) {
|
val type = when (val kind = constExpression.kind) {
|
||||||
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> {
|
ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> {
|
||||||
val integerLiteralType =
|
val expressionType = ConeIntegerLiteralTypeImpl.create(
|
||||||
ConeIntegerLiteralTypeImpl(constExpression.value as Long, isUnsigned = kind == ConstantValueKind.UnsignedIntegerLiteral)
|
constExpression.value as Long,
|
||||||
if (data.expectedType != null) {
|
isUnsigned = kind == ConstantValueKind.UnsignedIntegerLiteral
|
||||||
val coneType = data.expectedType?.coneTypeSafe<ConeKotlinType>()?.fullyExpandedType(session)
|
)
|
||||||
val approximatedType = integerLiteralType.getApproximatedType(coneType)
|
val expectedTypeRef = data.expectedType
|
||||||
val newConstKind = approximatedType.toConstKind()
|
@Suppress("UNCHECKED_CAST")
|
||||||
@Suppress("UNCHECKED_CAST")
|
when {
|
||||||
constExpression.replaceKind(newConstKind as ConstantValueKind<T>)
|
expressionType is ConeClassLikeType -> {
|
||||||
approximatedType
|
constExpression.replaceKind(expressionType.toConstKind() as ConstantValueKind<T>)
|
||||||
} else {
|
expressionType
|
||||||
integerLiteralType
|
}
|
||||||
|
expectedTypeRef != null -> {
|
||||||
|
require(expressionType is ConeIntegerLiteralTypeImpl)
|
||||||
|
val coneType = expectedTypeRef.coneTypeSafe<ConeKotlinType>()?.fullyExpandedType(session)
|
||||||
|
val approximatedType= expressionType.getApproximatedType(coneType)
|
||||||
|
constExpression.replaceKind(approximatedType.toConstKind() as ConstantValueKind<T>)
|
||||||
|
approximatedType
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
expressionType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> kind.expectedConeType(session)
|
else -> kind.expectedConeType(session)
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ fun ConeClassLikeType.isByte(): Boolean = lookupTag.classId == StandardClassIds.
|
|||||||
fun ConeClassLikeType.isBoolean(): Boolean = lookupTag.classId == StandardClassIds.Boolean
|
fun ConeClassLikeType.isBoolean(): Boolean = lookupTag.classId == StandardClassIds.Boolean
|
||||||
fun ConeClassLikeType.isChar(): Boolean = lookupTag.classId == StandardClassIds.Char
|
fun ConeClassLikeType.isChar(): Boolean = lookupTag.classId == StandardClassIds.Char
|
||||||
|
|
||||||
|
fun ConeClassLikeType.isULong(): Boolean = lookupTag.classId == StandardClassIds.ULong
|
||||||
|
|
||||||
fun ConeClassLikeType.isPrimitiveType(): Boolean =
|
fun ConeClassLikeType.isPrimitiveType(): Boolean =
|
||||||
isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar()
|
isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar()
|
||||||
|
|
||||||
|
|||||||
+53
-47
@@ -5,61 +5,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.types
|
package org.jetbrains.kotlin.fir.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.isLong
|
||||||
|
import org.jetbrains.kotlin.fir.isULong
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
|
|
||||||
class ConeIntegerLiteralTypeImpl : ConeIntegerLiteralType {
|
class ConeIntegerLiteralTypeImpl(
|
||||||
override val possibleTypes: Collection<ConeClassLikeType>
|
value: Long,
|
||||||
|
override val possibleTypes: Collection<ConeClassLikeType>,
|
||||||
|
isUnsigned: Boolean,
|
||||||
|
nullability: ConeNullability
|
||||||
|
) : ConeIntegerLiteralType(value, isUnsigned, nullability) {
|
||||||
override val attributes: ConeAttributes
|
override val attributes: ConeAttributes
|
||||||
get() = ConeAttributes.Empty
|
get() = ConeAttributes.Empty
|
||||||
|
|
||||||
constructor(
|
|
||||||
value: Long,
|
|
||||||
isUnsigned: Boolean,
|
|
||||||
nullability: ConeNullability = ConeNullability.NOT_NULL
|
|
||||||
) : super(value, isUnsigned, nullability) {
|
|
||||||
possibleTypes = mutableListOf()
|
|
||||||
|
|
||||||
fun checkBoundsAndAddPossibleType(classId: ClassId, range: LongRange) {
|
|
||||||
if (value in range) {
|
|
||||||
possibleTypes.add(createType(classId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addSignedPossibleTypes() {
|
|
||||||
checkBoundsAndAddPossibleType(StandardClassIds.Int, INT_RANGE)
|
|
||||||
possibleTypes += createType(StandardClassIds.Long)
|
|
||||||
checkBoundsAndAddPossibleType(StandardClassIds.Byte, BYTE_RANGE)
|
|
||||||
checkBoundsAndAddPossibleType(StandardClassIds.Short, SHORT_RANGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addUnsignedPossibleType() {
|
|
||||||
checkBoundsAndAddPossibleType(StandardClassIds.UInt, UINT_RANGE)
|
|
||||||
possibleTypes += createType(StandardClassIds.ULong)
|
|
||||||
checkBoundsAndAddPossibleType(StandardClassIds.UByte, UBYTE_RANGE)
|
|
||||||
checkBoundsAndAddPossibleType(StandardClassIds.UShort, USHORT_RANGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUnsigned) {
|
|
||||||
addUnsignedPossibleType()
|
|
||||||
} else {
|
|
||||||
addSignedPossibleTypes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private constructor(
|
|
||||||
value: Long,
|
|
||||||
possibleTypes: Collection<ConeClassLikeType>,
|
|
||||||
isUnsigned: Boolean,
|
|
||||||
nullability: ConeNullability = ConeNullability.NOT_NULL
|
|
||||||
) : super(value, isUnsigned, nullability) {
|
|
||||||
this.possibleTypes = possibleTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
override val supertypes: List<ConeClassLikeType> by lazy {
|
override val supertypes: List<ConeClassLikeType> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
createType(StandardClassIds.Number),
|
createType(StandardClassIds.Number),
|
||||||
@@ -79,6 +42,49 @@ class ConeIntegerLiteralTypeImpl : ConeIntegerLiteralType {
|
|||||||
|
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
companion object {
|
companion object {
|
||||||
|
fun create(
|
||||||
|
value: Long,
|
||||||
|
isUnsigned: Boolean,
|
||||||
|
nullability: ConeNullability = ConeNullability.NOT_NULL
|
||||||
|
): ConeSimpleKotlinType {
|
||||||
|
val possibleTypes = mutableListOf<ConeClassLikeType>()
|
||||||
|
|
||||||
|
fun checkBoundsAndAddPossibleType(classId: ClassId, range: LongRange) {
|
||||||
|
if (value in range) {
|
||||||
|
possibleTypes.add(createType(classId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addSignedPossibleTypes() {
|
||||||
|
checkBoundsAndAddPossibleType(StandardClassIds.Int, INT_RANGE)
|
||||||
|
possibleTypes += createType(StandardClassIds.Long)
|
||||||
|
checkBoundsAndAddPossibleType(StandardClassIds.Byte, BYTE_RANGE)
|
||||||
|
checkBoundsAndAddPossibleType(StandardClassIds.Short, SHORT_RANGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addUnsignedPossibleType() {
|
||||||
|
checkBoundsAndAddPossibleType(StandardClassIds.UInt, UINT_RANGE)
|
||||||
|
possibleTypes += createType(StandardClassIds.ULong)
|
||||||
|
checkBoundsAndAddPossibleType(StandardClassIds.UByte, UBYTE_RANGE)
|
||||||
|
checkBoundsAndAddPossibleType(StandardClassIds.UShort, USHORT_RANGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUnsigned) {
|
||||||
|
addUnsignedPossibleType()
|
||||||
|
} else {
|
||||||
|
addSignedPossibleTypes()
|
||||||
|
}
|
||||||
|
return if (possibleTypes.size == 1) {
|
||||||
|
possibleTypes.single().withNullability(nullability).also {
|
||||||
|
if (AbstractTypeChecker.RUN_SLOW_ASSERTIONS) {
|
||||||
|
assert(it.isLong() || it.isULong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ConeIntegerLiteralTypeImpl(value, possibleTypes, isUnsigned, nullability)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createType(classId: ClassId): ConeClassLikeType {
|
private fun createType(classId: ClassId): ConeClassLikeType {
|
||||||
return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(classId), emptyArray(), false)
|
return ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(classId), emptyArray(), false)
|
||||||
}
|
}
|
||||||
@@ -137,7 +143,7 @@ class ConeIntegerLiteralTypeImpl : ConeIntegerLiteralType {
|
|||||||
Mode.COMMON_SUPER_TYPE -> left.possibleTypes intersect right.possibleTypes
|
Mode.COMMON_SUPER_TYPE -> left.possibleTypes intersect right.possibleTypes
|
||||||
Mode.INTERSECTION_TYPE -> left.possibleTypes union right.possibleTypes
|
Mode.INTERSECTION_TYPE -> left.possibleTypes union right.possibleTypes
|
||||||
}
|
}
|
||||||
return ConeIntegerLiteralTypeImpl(left.value, possibleTypes, left.isUnsigned)
|
return ConeIntegerLiteralTypeImpl(left.value, possibleTypes, left.isUnsigned, left.nullability)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fold(left: ConeIntegerLiteralType, right: SimpleTypeMarker): SimpleTypeMarker? =
|
private fun fold(left: ConeIntegerLiteralType, right: SimpleTypeMarker): SimpleTypeMarker? =
|
||||||
|
|||||||
Reference in New Issue
Block a user