Treat number with unsigned literal as UByte & UShort & UInt & ULong

This commit is contained in:
Mikhail Zarechenskiy
2018-05-28 10:54:09 +03:00
parent 656f6cbded
commit 7d5fdb660d
15 changed files with 217 additions and 75 deletions
@@ -29,7 +29,7 @@ class JavaPropertyInitializerEvaluatorImpl : JavaPropertyInitializerEvaluator {
//Note: evaluated expression may be of class that does not match field type in some cases
// tested for Int, left other checks just in case
is Byte, is Short, is Int, is Long -> {
ConstantValueFactory.createIntegerConstantValue((evaluated as Number).toLong(), descriptor.type)
ConstantValueFactory.createIntegerConstantValue((evaluated as Number).toLong(), descriptor.type, false)
}
else -> {
ConstantValueFactory.createConstantValue(evaluated)
@@ -387,11 +387,18 @@ private class ConstantExpressionEvaluatorVisitor(
}
}
val isLongWithSuffix = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text)
val isUnsigned = hasUnsignedSuffix(text)
val typedConstant = nodeElementType == KtNodeTypes.INTEGER_CONSTANT && (hasLongSuffix(text) || isUnsigned)
return createConstant(
result,
expectedType,
CompileTimeConstant.Parameters(true, !isLongWithSuffix, false, usesNonConstValAsConstant = false)
CompileTimeConstant.Parameters(
canBeUsedInAnnotation = true,
isPure = !typedConstant,
isUnsigned = isUnsigned,
usesVariableAsConstant = false,
usesNonConstValAsConstant = false
)
)
}
@@ -435,6 +442,7 @@ private class ConstantExpressionEvaluatorVisitor(
expectedType,
CompileTimeConstant.Parameters(
isPure = false,
isUnsigned = false,
canBeUsedInAnnotation = canBeUsedInAnnotation,
usesVariableAsConstant = usesVariableAsConstant,
usesNonConstValAsConstant = usesNonConstantVariableAsConstant
@@ -497,6 +505,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation = true,
isPure = false,
isUnsigned = false,
usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant,
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant
)
@@ -544,6 +553,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation,
!isNumberConversionMethod && isArgumentPure,
false,
usesVariableAsConstant, usesNonConstValAsConstant
)
)
@@ -575,8 +585,9 @@ private class ConstantExpressionEvaluatorVisitor(
usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression)
val usesNonConstValAsConstant =
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
val parameters =
CompileTimeConstant.Parameters(canBeUsedInAnnotation, areArgumentsPure, usesVariableAsConstant, usesNonConstValAsConstant)
val parameters = CompileTimeConstant.Parameters(
canBeUsedInAnnotation, areArgumentsPure, false, usesVariableAsConstant, usesNonConstValAsConstant
)
return when (resultingDescriptorName) {
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
OperatorNameConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression)?.wrap(parameters)
@@ -696,6 +707,7 @@ private class ConstantExpressionEvaluatorVisitor(
CompileTimeConstant.Parameters(
canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor),
isPure = false,
isUnsigned = false,
usesVariableAsConstant = true,
usesNonConstValAsConstant = !callableDescriptor.isConst
)
@@ -899,7 +911,7 @@ private class ConstantExpressionEvaluatorVisitor(
expectedType: KotlinType?,
parameters: CompileTimeConstant.Parameters
): CompileTimeConstant<*>? {
return if (parameters.isPure) {
return if (parameters.isPure || parameters.isUnsigned) {
return createCompileTimeConstant(value, parameters, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
} else {
ConstantValueFactory.createConstantValue(value)?.wrap(parameters)
@@ -923,15 +935,17 @@ private class ConstantExpressionEvaluatorVisitor(
expectedType: KotlinType
): CompileTimeConstant<*>? {
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
return IntegerValueTypeConstant(value, builtIns, parameters)
return IntegerValueTypeConstant(value, constantExpressionEvaluator.module, parameters)
}
val integerValue = ConstantValueFactory.createIntegerConstantValue(value, expectedType)
val integerValue = ConstantValueFactory.createIntegerConstantValue(value, expectedType, parameters.isUnsigned)
if (integerValue != null) {
return integerValue.wrap(parameters)
}
return when (value) {
value.toInt().toLong() -> IntValue(value.toInt())
else -> LongValue(value)
value.toInt().toLong() ->
if (parameters.isUnsigned) UIntValue(value.toInt()) else IntValue(value.toInt())
else ->
if (parameters.isUnsigned) ULongValue(value) else LongValue(value)
}.wrap(parameters)
}
@@ -941,13 +955,15 @@ private class ConstantExpressionEvaluatorVisitor(
private fun <T> ConstantValue<T>.wrap(
canBeUsedInAnnotation: Boolean = this !is NullValue,
isPure: Boolean = false,
isUnsigned: Boolean = false,
usesVariableAsConstant: Boolean = false,
usesNonConstValAsConstant: Boolean = false
): TypedCompileTimeConstant<T> =
wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, usesVariableAsConstant, usesNonConstValAsConstant))
wrap(CompileTimeConstant.Parameters(canBeUsedInAnnotation, isPure, isUnsigned, usesVariableAsConstant, usesNonConstValAsConstant))
}
private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L')
private fun hasUnsignedSuffix(text: String) = text.endsWith('u')
private fun parseNumericLiteral(text: String, type: IElementType): Any? {
val canonicalText = LiteralFormatUtil.removeUnderscores(text)
@@ -960,8 +976,8 @@ private fun parseNumericLiteral(text: String, type: IElementType): Any? {
private fun parseLong(text: String): Long? {
try {
fun substringLongSuffix(s: String) = if (hasLongSuffix(text)) s.substring(0, s.length - 1) else s
fun parseLong(text: String, radix: Int) = java.lang.Long.parseLong(substringLongSuffix(text), radix)
fun substringSuffix(s: String) = if (hasLongSuffix(text) || hasUnsignedSuffix(text)) s.substring(0, s.length - 1) else s
fun parseLong(text: String, radix: Int) = java.lang.Long.parseLong(substringSuffix(text), radix)
val (number, radix) = extractRadix(text)
return parseLong(number, radix)
@@ -0,0 +1,16 @@
// !LANGUAGE: +InlineClasses
// !SKIP_METADATA_VERSION_CHECK
// WITH_UNSIGNED
fun box(): String {
val u1 = 1u
val u2 = 2u
val u3 = u1 + u2
if (u3.toInt() != 3) return "fail"
val max = 0u.dec().toLong()
val expected = Int.MAX_VALUE * 2L + 1
if (max != expected) return "fail"
return "OK"
}
@@ -1,11 +0,0 @@
// !LANGUAGE: +InlineClasses
// !SKIP_METADATA_VERSION_CHECK
// WITH_UNSIGNED
@Suppress("INVISIBLE_MEMBER")
fun box(): String {
val u1 = UInt(1)
val u2 = UInt(2)
val u3 = u1 + u2
return if (u3.toInt() == 3) "OK" else "fail"
}
@@ -25,8 +25,10 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.TypeResolver
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -64,8 +66,13 @@ class ConstraintSystemTestData(
val matcher = INTEGER_VALUE_TYPE_PATTERN.matcher(name)
if (matcher.find()) {
val number = matcher.group(1)!!
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(Annotations.EMPTY, IntegerValueTypeConstructor(number.toLong(), functionFoo.builtIns),
listOf(), false, MemberScope.Empty
val parameters = CompileTimeConstant.Parameters(false, false, false, false, false)
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY,
IntegerValueTypeConstructor(number.toLong(), functionFoo.module, parameters),
listOf(),
false,
MemberScope.Empty
)
}
return typeResolver.resolveType(
@@ -11179,6 +11179,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
}
@TestMetadata("checkBasicUnsignedLiterals.kt")
public void testCheckBasicUnsignedLiterals() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBasicUnsignedLiterals.kt");
}
@TestMetadata("checkBoxUnboxOfArgumentsOnInlinedFunctions.kt")
public void testCheckBoxUnboxOfArgumentsOnInlinedFunctions() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBoxUnboxOfArgumentsOnInlinedFunctions.kt");
@@ -11229,11 +11234,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/checkLambdaWithInlineClassesInFunctionalType.kt");
}
@TestMetadata("checkPlusOfUInt.kt")
public void testCheckPlusOfUInt() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkPlusOfUInt.kt");
}
@TestMetadata("checkUnboxingResultFromTypeVariable.kt")
public void testCheckUnboxingResultFromTypeVariable() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt");
@@ -11179,6 +11179,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
}
@TestMetadata("checkBasicUnsignedLiterals.kt")
public void testCheckBasicUnsignedLiterals() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBasicUnsignedLiterals.kt");
}
@TestMetadata("checkBoxUnboxOfArgumentsOnInlinedFunctions.kt")
public void testCheckBoxUnboxOfArgumentsOnInlinedFunctions() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBoxUnboxOfArgumentsOnInlinedFunctions.kt");
@@ -11229,11 +11234,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/checkLambdaWithInlineClassesInFunctionalType.kt");
}
@TestMetadata("checkPlusOfUInt.kt")
public void testCheckPlusOfUInt() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkPlusOfUInt.kt");
}
@TestMetadata("checkUnboxingResultFromTypeVariable.kt")
public void testCheckUnboxingResultFromTypeVariable() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt");
@@ -11179,6 +11179,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
}
@TestMetadata("checkBasicUnsignedLiterals.kt")
public void testCheckBasicUnsignedLiterals() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBasicUnsignedLiterals.kt");
}
@TestMetadata("checkBoxUnboxOfArgumentsOnInlinedFunctions.kt")
public void testCheckBoxUnboxOfArgumentsOnInlinedFunctions() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBoxUnboxOfArgumentsOnInlinedFunctions.kt");
@@ -11229,11 +11234,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/checkLambdaWithInlineClassesInFunctionalType.kt");
}
@TestMetadata("checkPlusOfUInt.kt")
public void testCheckPlusOfUInt() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkPlusOfUInt.kt");
}
@TestMetadata("checkUnboxingResultFromTypeVariable.kt")
public void testCheckUnboxingResultFromTypeVariable() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt");
@@ -332,6 +332,15 @@ public abstract class KotlinBuiltIns {
public final FqNameUnsafe kMutableProperty2 = reflect("KMutableProperty2");
public final ClassId kProperty = ClassId.topLevel(reflect("KProperty").toSafe());
public final FqName uByteFqName = fqName("UByte");
public final FqName uShortFqName = fqName("UShort");
public final FqName uIntFqName = fqName("UInt");
public final FqName uLongFqName = fqName("ULong");
public final ClassId uByte = ClassId.topLevel(uByteFqName);
public final ClassId uShort = ClassId.topLevel(uShortFqName);
public final ClassId uInt = ClassId.topLevel(uIntFqName);
public final ClassId uLong = ClassId.topLevel(uLongFqName);
public final Set<Name> primitiveTypeShortNames = newHashSetWithExpectedSize(PrimitiveType.values().length);
public final Set<Name> primitiveArrayTypeShortNames = newHashSetWithExpectedSize(PrimitiveType.values().length);
public final Map<FqNameUnsafe, PrimitiveType> fqNameToPrimitiveType = newHashMapWithExpectedSize(PrimitiveType.values().length);
@@ -975,6 +984,22 @@ public abstract class KotlinBuiltIns {
return isDoubleOrNullableDouble(type) && !type.isMarkedNullable();
}
public static boolean isUByte(@NotNull KotlinType type) {
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uByteFqName.toUnsafe());
}
public static boolean isUShort(@NotNull KotlinType type) {
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uShortFqName.toUnsafe());
}
public static boolean isUInt(@NotNull KotlinType type) {
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uIntFqName.toUnsafe());
}
public static boolean isULong(@NotNull KotlinType type) {
return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.uLongFqName.toUnsafe());
}
public static boolean isDoubleOrNullableDouble(@NotNull KotlinType type) {
return isConstructedFromGivenClass(type, FQ_NAMES._double);
}
@@ -42,9 +42,12 @@ interface CompileTimeConstant<out T> {
val isPure: Boolean get() = parameters.isPure
val isUnsigned: Boolean get() = parameters.isUnsigned
class Parameters(
val canBeUsedInAnnotation: Boolean,
val isPure: Boolean,
val isUnsigned: Boolean,
val usesVariableAsConstant: Boolean,
val usesNonConstValAsConstant: Boolean
)
@@ -84,10 +87,10 @@ class TypedCompileTimeConstant<out T>(
class IntegerValueTypeConstant(
private val value: Number,
builtIns: KotlinBuiltIns,
module: ModuleDescriptor,
override val parameters: CompileTimeConstant.Parameters
) : CompileTimeConstant<Number> {
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), builtIns)
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters)
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
val type = getType(expectedType)
@@ -95,6 +98,13 @@ class IntegerValueTypeConstant(
KotlinBuiltIns.isInt(type) -> IntValue(value.toInt())
KotlinBuiltIns.isByte(type) -> ByteValue(value.toByte())
KotlinBuiltIns.isShort(type) -> ShortValue(value.toShort())
KotlinBuiltIns.isLong(type) -> LongValue(value.toLong())
KotlinBuiltIns.isUInt(type) -> UIntValue(value.toInt())
KotlinBuiltIns.isUByte(type) -> UByteValue(value.toByte())
KotlinBuiltIns.isUShort(type) -> UShortValue(value.toShort())
KotlinBuiltIns.isULong(type) -> ULongValue(value.toLong())
else -> LongValue(value.toLong())
}
}
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.resolve.constants
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -51,10 +50,10 @@ object ConstantValueFactory {
fun createUnsignedValue(constantValue: ConstantValue<*>, type: KotlinType): UnsignedValueConstant<*>? {
return when (constantValue) {
is ByteValue -> UByteValue(constantValue, type)
is ShortValue -> UShortValue(constantValue, type)
is IntValue -> UIntValue(constantValue, type)
is LongValue -> ULongValue(constantValue, type)
is ByteValue -> UByteValue(constantValue.value)
is ShortValue -> UShortValue(constantValue.value)
is IntValue -> UIntValue(constantValue.value)
is LongValue -> ULongValue(constantValue.value)
else -> null
}
}
@@ -66,16 +65,27 @@ object ConstantValueFactory {
fun createIntegerConstantValue(
value: Long,
expectedType: KotlinType
expectedType: KotlinType,
isUnsigned: Boolean
): ConstantValue<*>? {
val notNullExpected = TypeUtils.makeNotNullable(expectedType)
return when {
KotlinBuiltIns.isLong(notNullExpected) -> LongValue(value)
KotlinBuiltIns.isInt(notNullExpected) && value == value.toInt().toLong() -> IntValue(value.toInt())
KotlinBuiltIns.isShort(notNullExpected) && value == value.toShort().toLong() -> ShortValue(value.toShort())
KotlinBuiltIns.isByte(notNullExpected) && value == value.toByte().toLong() -> ByteValue(value.toByte())
KotlinBuiltIns.isChar(notNullExpected) -> IntValue(value.toInt())
else -> null
return if (isUnsigned) {
when {
KotlinBuiltIns.isUByte(notNullExpected) && value == value.toByte().toLong() -> UByteValue(value.toByte())
KotlinBuiltIns.isUShort(notNullExpected) && value == value.toShort().toLong() -> UShortValue(value.toShort())
KotlinBuiltIns.isUInt(notNullExpected) && value == value.toInt().toLong() -> UIntValue(value.toInt())
KotlinBuiltIns.isULong(notNullExpected) -> ULongValue(value)
else -> null
}
} else {
when {
KotlinBuiltIns.isLong(notNullExpected) -> LongValue(value)
KotlinBuiltIns.isInt(notNullExpected) && value == value.toInt().toLong() -> IntValue(value.toInt())
KotlinBuiltIns.isShort(notNullExpected) && value == value.toShort().toLong() -> ShortValue(value.toShort())
KotlinBuiltIns.isByte(notNullExpected) && value == value.toByte().toLong() -> ByteValue(value.toByte())
KotlinBuiltIns.isChar(notNullExpected) -> IntValue(value.toInt())
else -> null
}
}
}
}
@@ -17,14 +17,20 @@
package org.jetbrains.kotlin.resolve.constants
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeConstructor
import java.util.*
class IntegerValueTypeConstructor(
private val value: Long,
private val builtIns: KotlinBuiltIns
private val value: Long,
private val module: ModuleDescriptor,
parameters: CompileTimeConstant.Parameters
) : TypeConstructor {
private val supertypes = ArrayList<KotlinType>(4)
@@ -32,10 +38,28 @@ class IntegerValueTypeConstructor(
// order of types matters
// 'getPrimitiveNumberType' returns first of supertypes that is a subtype of expected type
// for expected type 'Any' result type 'Int' should be returned
checkBoundsAndAddSuperType(value, Integer.MIN_VALUE.toLong(), Integer.MAX_VALUE.toLong(), builtIns.intType)
checkBoundsAndAddSuperType(value, java.lang.Byte.MIN_VALUE.toLong(), java.lang.Byte.MAX_VALUE.toLong(), builtIns.byteType)
checkBoundsAndAddSuperType(value, java.lang.Short.MIN_VALUE.toLong(), java.lang.Short.MAX_VALUE.toLong(), builtIns.shortType)
supertypes.add(builtIns.longType)
val isUnsigned = parameters.isUnsigned
// TODO: fix value ranges for unsigned types
checkBoundsAndAddSuperType(
value,
Integer.MIN_VALUE.toLong(),
Integer.MAX_VALUE.toLong(),
if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uInt) else builtIns.intType
)
checkBoundsAndAddSuperType(
value,
java.lang.Byte.MIN_VALUE.toLong(),
java.lang.Byte.MAX_VALUE.toLong(),
if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uByte) else builtIns.byteType
)
checkBoundsAndAddSuperType(
value,
java.lang.Short.MIN_VALUE.toLong(),
java.lang.Short.MAX_VALUE.toLong(),
if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uShort) else builtIns.shortType
)
supertypes.add(if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uLong) else builtIns.longType)
}
private fun checkBoundsAndAddSuperType(value: Long, minValue: Long, maxValue: Long, kotlinType: KotlinType) {
@@ -44,6 +68,9 @@ class IntegerValueTypeConstructor(
}
}
private fun unsignedType(classId: ClassId): SimpleType =
module.findClassAcrossModuleDependencies(classId)?.defaultType ?: ErrorUtils.createErrorType("Error type for $classId")
override fun getSupertypes(): Collection<KotlinType> = supertypes
override fun getParameters(): List<TypeParameterDescriptor> = emptyList()
@@ -57,7 +84,7 @@ class IntegerValueTypeConstructor(
fun getValue(): Long = value
override fun getBuiltIns(): KotlinBuiltIns {
return builtIns
return module.builtIns
}
override fun toString() = "IntegerValueType($value)"
@@ -40,9 +40,7 @@ abstract class ConstantValue<out T>(open val value: T) {
}
abstract class IntegerValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
abstract class UnsignedValueConstant<out T> protected constructor(value: T, private val kotlinType: KotlinType) : ConstantValue<T>(value) {
override fun getType(module: ModuleDescriptor): KotlinType = kotlinType
}
abstract class UnsignedValueConstant<out T> protected constructor(value: T) : ConstantValue<T>(value)
class AnnotationValue(value: AnnotationDescriptor) : ConstantValue<AnnotationDescriptor>(value) {
override fun getType(module: ModuleDescriptor): KotlinType = value.type
@@ -193,25 +191,45 @@ class StringValue(value: String) : ConstantValue<String>(value) {
override fun toString() = "\"$value\""
}
class UByteValue(byteValue: ByteValue, kotlinType: KotlinType) : UnsignedValueConstant<Byte>(byteValue.value, kotlinType) {
class UByteValue(byteValue: Byte) : UnsignedValueConstant<Byte>(byteValue) {
override fun getType(module: ModuleDescriptor): KotlinType {
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uByte)?.defaultType
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
}
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUByteValue(this, data)
override fun toString() = "$value.toUByte()"
}
class UShortValue(shortValue: ShortValue, kotlinType: KotlinType) : UnsignedValueConstant<Short>(shortValue.value, kotlinType) {
class UShortValue(shortValue: Short) : UnsignedValueConstant<Short>(shortValue) {
override fun getType(module: ModuleDescriptor): KotlinType {
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uShort)?.defaultType
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
}
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitUShortValue(this, data)
override fun toString() = "$value.toUShort()"
}
class UIntValue(intValue: IntValue, kotlinType: KotlinType) : UnsignedValueConstant<Int>(intValue.value, kotlinType) {
class UIntValue(intValue: Int) : UnsignedValueConstant<Int>(intValue) {
override fun getType(module: ModuleDescriptor): KotlinType {
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uInt)?.defaultType
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
}
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D) = visitor.visitUIntValue(this, data)
override fun toString() = "$value.toUInt()"
}
class ULongValue(longValue: LongValue, kotlinType: KotlinType) : UnsignedValueConstant<Long>(longValue.value, kotlinType) {
class ULongValue(longValue: Long) : UnsignedValueConstant<Long>(longValue) {
override fun getType(module: ModuleDescriptor): KotlinType {
return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uLong)?.defaultType
?: ErrorUtils.createErrorType("Unsigned type UByte not found")
}
override fun <R, D> accept(visitor: AnnotationArgumentVisitor<R, D>, data: D): R = visitor.visitULongValue(this, data)
override fun toString() = "$value.toULong()"
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
@@ -445,6 +448,27 @@ public class TypeUtils {
if (supertypes.contains(longType)) {
return longType;
}
KotlinType uIntType = findByFqName(supertypes, KotlinBuiltIns.FQ_NAMES.uIntFqName);
if (uIntType != null) return uIntType;
KotlinType uLongType = findByFqName(supertypes, KotlinBuiltIns.FQ_NAMES.uLongFqName);
if (uLongType != null) return uLongType;
return null;
}
@Nullable
private static KotlinType findByFqName(@NotNull Collection<KotlinType> supertypes, FqName fqName) {
for (KotlinType supertype : supertypes) {
ClassifierDescriptor descriptor = supertype.getConstructor().getDeclarationDescriptor();
if (descriptor == null) continue;
FqNameUnsafe descriptorFqName = DescriptorUtils.getFqName(descriptor);
if (descriptorFqName.equals(fqName.toUnsafe())) {
return supertype;
}
}
return null;
}
@@ -9715,6 +9715,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
}
@TestMetadata("checkBasicUnsignedLiterals.kt")
public void testCheckBasicUnsignedLiterals() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBasicUnsignedLiterals.kt");
}
@TestMetadata("checkBoxUnboxOfArgumentsOnInlinedFunctions.kt")
public void testCheckBoxUnboxOfArgumentsOnInlinedFunctions() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkBoxUnboxOfArgumentsOnInlinedFunctions.kt");
@@ -9765,11 +9770,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/checkLambdaWithInlineClassesInFunctionalType.kt");
}
@TestMetadata("checkPlusOfUInt.kt")
public void testCheckPlusOfUInt() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkPlusOfUInt.kt");
}
@TestMetadata("checkUnboxingResultFromTypeVariable.kt")
public void testCheckUnboxingResultFromTypeVariable() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt");