Introduce conversions from signed pure constants to unsigned ones
#KT-24717 In Progress #KT-25996 Open #KT-25997 Open
This commit is contained in:
@@ -48,6 +48,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.jetbrains.kotlin.util.slicedMap.RewritePolicy.DO_NOTHING;
|
||||
import static org.jetbrains.kotlin.util.slicedMap.Slices.COMPILE_TIME_VALUE_REWRITE_POLICY;
|
||||
|
||||
public interface BindingContext {
|
||||
BindingContext EMPTY = new BindingContext() {
|
||||
@@ -89,7 +90,7 @@ public interface BindingContext {
|
||||
|
||||
WritableSlice<KtAnnotationEntry, AnnotationDescriptor> ANNOTATION = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<KtExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice();
|
||||
WritableSlice<KtExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = new BasicWritableSlice<>(COMPILE_TIME_VALUE_REWRITE_POLICY);
|
||||
|
||||
WritableSlice<KtTypeReference, KotlinType> TYPE = Slices.createSimpleSlice();
|
||||
WritableSlice<KtTypeReference, KotlinType> ABBREVIATED_TYPE = Slices.createSimpleSlice();
|
||||
|
||||
@@ -23,15 +23,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.name.SpecialNames;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.TypeResolver;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
@@ -41,6 +40,8 @@ import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||
@@ -69,6 +70,7 @@ public class ArgumentTypeResolver {
|
||||
@NotNull private final ReflectionTypes reflectionTypes;
|
||||
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||
@NotNull private final FunctionPlaceholders functionPlaceholders;
|
||||
@NotNull private final ModuleDescriptor moduleDescriptor;
|
||||
|
||||
private ExpressionTypingServices expressionTypingServices;
|
||||
|
||||
@@ -78,7 +80,8 @@ public class ArgumentTypeResolver {
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull ReflectionTypes reflectionTypes,
|
||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||
@NotNull FunctionPlaceholders functionPlaceholders
|
||||
@NotNull FunctionPlaceholders functionPlaceholders,
|
||||
@NotNull ModuleDescriptor moduleDescriptor
|
||||
) {
|
||||
this.typeResolver = typeResolver;
|
||||
this.doubleColonExpressionResolver = doubleColonExpressionResolver;
|
||||
@@ -86,6 +89,7 @@ public class ArgumentTypeResolver {
|
||||
this.reflectionTypes = reflectionTypes;
|
||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||
this.functionPlaceholders = functionPlaceholders;
|
||||
this.moduleDescriptor = moduleDescriptor;
|
||||
}
|
||||
|
||||
// component dependency cycle
|
||||
@@ -218,6 +222,11 @@ public class ArgumentTypeResolver {
|
||||
return expressionTypingServices.getTypeInfo(expression, newContext);
|
||||
}
|
||||
|
||||
// TODO: probably should be "is unsigned type or is supertype of unsigned type" to support Comparable<UInt> expected types too
|
||||
if (UnsignedTypes.INSTANCE.isUnsignedType(context.expectedType)) {
|
||||
convertSignedConstantToUnsigned(expression, context);
|
||||
}
|
||||
|
||||
KotlinTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
|
||||
if (recordedTypeInfo != null) {
|
||||
return recordedTypeInfo;
|
||||
@@ -228,6 +237,28 @@ public class ArgumentTypeResolver {
|
||||
return expressionTypingServices.getTypeInfo(expression, newContext);
|
||||
}
|
||||
|
||||
private void convertSignedConstantToUnsigned(
|
||||
@NotNull KtExpression expression,
|
||||
@NotNull CallResolutionContext<?> context
|
||||
) {
|
||||
CompileTimeConstant<?> constant = context.trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||
if (!(constant instanceof IntegerValueTypeConstant) || !constantCanBeConvertedToUnsigned(constant)) return;
|
||||
|
||||
IntegerValueTypeConstant unsignedConstant = IntegerValueTypeConstant.convertToUnsignedConstant(
|
||||
(IntegerValueTypeConstant) constant, moduleDescriptor
|
||||
);
|
||||
|
||||
context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, unsignedConstant);
|
||||
|
||||
updateResultArgumentTypeIfNotDenotable(
|
||||
context.trace, context.statementFilter, context.expectedType, unsignedConstant.getUnknownIntegerType(), expression
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean constantCanBeConvertedToUnsigned(@NotNull CompileTimeConstant<?> constant) {
|
||||
return !constant.isError() && constant.getParameters().isPure();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KotlinTypeInfo getCallableReferenceTypeInfo(
|
||||
@NotNull KtExpression expression,
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||
@@ -309,9 +310,7 @@ class CallCompleter(
|
||||
|
||||
private fun createTypeForConvertableConstant(constant: CompileTimeConstant<*>): SimpleType? {
|
||||
val value = constant.getValue(TypeUtils.NO_EXPECTED_TYPE).safeAs<Number>()?.toLong() ?: return null
|
||||
val typeConstructor = IntegerValueTypeConstructor(
|
||||
value, moduleDescriptor, constant.parameters
|
||||
)
|
||||
val typeConstructor = IntegerValueTypeConstructor(value, moduleDescriptor, constant.parameters)
|
||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||
@@ -332,11 +331,17 @@ class CallCompleter(
|
||||
var updatedType: KotlinType? = recordedType
|
||||
|
||||
val results = completeCallForArgument(deparenthesized, context)
|
||||
|
||||
if (results != null && results.isSingleResult) {
|
||||
val resolvedCall = results.resultingCall
|
||||
updatedType = if (resolvedCall.hasInferredReturnType()) {
|
||||
resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context)
|
||||
} else null
|
||||
val constant = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized]
|
||||
if (constant !is IntegerValueTypeConstant || !constant.convertedFromSigned) {
|
||||
updatedType =
|
||||
if (resolvedCall.hasInferredReturnType())
|
||||
resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context)
|
||||
else
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
// For the cases like 'foo(1)' the type of '1' depends on expected type (it can be Int, Byte, etc.),
|
||||
|
||||
@@ -20,6 +20,9 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValueFactoryKt;
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -36,17 +39,47 @@ public class Slices {
|
||||
@Override
|
||||
public <K, V> boolean processRewrite(WritableSlice<K, V> slice, K key, V oldValue, V newValue) {
|
||||
if (!((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue)))) {
|
||||
// NOTE: Use BindingTraceContext.TRACK_REWRITES to debug this exception
|
||||
LOG.error("Rewrite at slice " + slice +
|
||||
" key: " + key +
|
||||
" old value: " + oldValue + '@' + System.identityHashCode(oldValue) +
|
||||
" new value: " + newValue + '@' + System.identityHashCode(newValue) +
|
||||
(key instanceof KtElement ? "\n" + PsiUtilsKt.getElementTextWithContext((KtElement) key) : ""));
|
||||
logErrorAboutRewritingNonEqualObjects(slice, key, oldValue, newValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Rewrite is allowed for equal objects and for signed constant values that were converted to unsigned ones
|
||||
// This is needed to avoid making `CompileTimeConstant` mutable
|
||||
public static final RewritePolicy COMPILE_TIME_VALUE_REWRITE_POLICY = new RewritePolicy() {
|
||||
@Override
|
||||
public <K> boolean rewriteProcessingNeeded(K key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> boolean processRewrite(WritableSlice<K, V> slice, K key, V oldValue, V newValue) {
|
||||
if ((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue))) return true;
|
||||
|
||||
if (oldValue instanceof IntegerValueTypeConstant && newValue instanceof IntegerValueTypeConstant) {
|
||||
IntegerValueTypeConstant oldConstant = (IntegerValueTypeConstant) oldValue;
|
||||
IntegerValueTypeConstant newConstant = (IntegerValueTypeConstant) newValue;
|
||||
|
||||
if (oldConstant.getParameters().isPure() && newConstant.getParameters().isUnsignedNumberLiteral()) {
|
||||
long oldConstantValue = oldConstant.getValue(TypeUtils.NO_EXPECTED_TYPE).longValue();
|
||||
Number newConstantValue = newConstant.getValue(TypeUtils.NO_EXPECTED_TYPE);
|
||||
if (oldConstantValue == newConstantValue.longValue() ||
|
||||
oldConstantValue == ConstantValueFactoryKt.fromUIntToLong(newConstantValue.intValue()) ||
|
||||
oldConstantValue == ConstantValueFactoryKt.fromUByteToLong(newConstantValue.byteValue()) ||
|
||||
oldConstantValue == ConstantValueFactoryKt.fromUShortToLong(newConstantValue.shortValue())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logErrorAboutRewritingNonEqualObjects(slice, key, oldValue, newValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private Slices() {
|
||||
}
|
||||
|
||||
@@ -118,4 +151,13 @@ public class Slices {
|
||||
return new BasicWritableSlice<>(rewritePolicy);
|
||||
}
|
||||
}
|
||||
|
||||
private static <K, V> void logErrorAboutRewritingNonEqualObjects(WritableSlice<K, V> slice, K key, V oldValue, V newValue) {
|
||||
// NOTE: Use BindingTraceContext.TRACK_REWRITES to debug this exception
|
||||
LOG.error("Rewrite at slice " + slice +
|
||||
" key: " + key +
|
||||
" old value: " + oldValue + '@' + System.identityHashCode(oldValue) +
|
||||
" new value: " + newValue + '@' + System.identityHashCode(newValue) +
|
||||
(key instanceof KtElement ? "\n" + PsiUtilsKt.getElementTextWithContext((KtElement) key) : ""));
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// WITH_UNSIGNED
|
||||
// IGNORE_BACKEND: JS_IR, JVM_IR, JS
|
||||
|
||||
fun takeUByte(u: UByte) = u.toByte()
|
||||
fun takeUShort(u: UShort) = u.toShort()
|
||||
fun takeUInt(u: UInt) = u.toInt()
|
||||
fun takeULong(u: ULong) = u.toLong()
|
||||
|
||||
fun box(): String {
|
||||
val b = takeUByte(200 + 55)
|
||||
if (b != (-1).toByte()) return "Fail 1: $b"
|
||||
|
||||
val s = takeUShort(123)
|
||||
if (s != 123.toShort()) return "Fail 2: $s"
|
||||
|
||||
val i = takeUInt(0xFFFF_FFFF)
|
||||
if (i != -1) return "Fail 3: $i"
|
||||
|
||||
val l = takeULong(0xFFFF_FFFF_FFFF)
|
||||
if (l != 0xFFFF_FFFF_FFFFL) return "Fail 4: $l"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE
|
||||
// !CHECK_TYPE
|
||||
|
||||
// Here we mostly trying to fix behaviour in order to track changes in inference rules for unsigned types later
|
||||
|
||||
fun <T> id(x: T): T = x
|
||||
fun <K> select(x: K, y: K): K = TODO()
|
||||
|
||||
fun takeUByte(u: UByte) {}
|
||||
|
||||
fun foo() {
|
||||
select(1, 1u) checkType { _<Comparable<*>>() }
|
||||
takeUByte(<!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>id(1)<!>)
|
||||
|
||||
1 <!NONE_APPLICABLE!>+<!> 1u
|
||||
(1u + 1) checkType { _<UInt>() }
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
public fun </*0*/ T> id(/*0*/ x: T): T
|
||||
public fun </*0*/ K> select(/*0*/ x: K, /*1*/ y: K): K
|
||||
public fun takeUByte(/*0*/ u: kotlin.UByte): kotlin.Unit
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun takeUByte(u: UByte) {}
|
||||
fun takeUShort(u: UShort) {}
|
||||
fun takeUInt(u: UInt) {}
|
||||
fun takeULong(u: ULong) {}
|
||||
|
||||
fun takeUBytes(vararg u: UByte) {}
|
||||
|
||||
fun takeNullableUInt(u: UInt?) {}
|
||||
|
||||
fun test() {
|
||||
takeUInt(1 + 2)
|
||||
takeUInt(1.plus(2))
|
||||
takeNullableUInt(4)
|
||||
|
||||
takeUInt(<!TYPE_MISMATCH!>Int.MAX_VALUE * 2L<!>)
|
||||
takeUInt(<!TYPE_MISMATCH!>-1<!>)
|
||||
takeUInt(<!TYPE_MISMATCH!>Int.MAX_VALUE * 2L + 2<!>)
|
||||
|
||||
takeUByte(1)
|
||||
takeUByte(255)
|
||||
takeUByte(<!TYPE_MISMATCH!>1.toByte()<!>)
|
||||
|
||||
takeUShort(1)
|
||||
takeUInt(1)
|
||||
takeULong(1)
|
||||
|
||||
takeULong(<!INT_LITERAL_OUT_OF_RANGE!>18446744073709551615<!>)
|
||||
takeULong(1844674407370955161)
|
||||
takeULong(18446744073709551615u)
|
||||
|
||||
takeUInt(<!INTEGER_OVERFLOW, TYPE_MISMATCH!>Int.MAX_VALUE * 2<!>)
|
||||
takeUInt(4294967294)
|
||||
|
||||
takeUBytes(1, 2, 255, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>256<!>, 0, <!TYPE_MISMATCH!>-1<!>, 40 + 2)
|
||||
|
||||
takeUInt(<!TYPE_MISMATCH!>1.myPlus(2)<!>)
|
||||
|
||||
val localVariable = 42
|
||||
takeUInt(<!TYPE_MISMATCH!>localVariable<!>)
|
||||
|
||||
var localMutableVariable = 42
|
||||
takeUInt(<!TYPE_MISMATCH!>localMutableVariable<!>)
|
||||
|
||||
val localNegativeVariable = -1
|
||||
takeUInt(<!TYPE_MISMATCH!>localNegativeVariable<!>)
|
||||
|
||||
takeUInt(<!TYPE_MISMATCH!>globalVariable<!>)
|
||||
|
||||
takeUInt(<!TYPE_MISMATCH!>constVal<!>)
|
||||
|
||||
takeUInt(<!TYPE_MISMATCH!>globalVariableWithGetter<!>)
|
||||
}
|
||||
|
||||
val globalVariable = 10
|
||||
|
||||
const val constVal = 10
|
||||
|
||||
val globalVariableWithGetter: Int get() = 0
|
||||
|
||||
val prop: UByte = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>255<!>
|
||||
|
||||
fun Int.myPlus(other: Int): Int = this + other
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package
|
||||
|
||||
public const val constVal: kotlin.Int = 10
|
||||
public val globalVariable: kotlin.Int = 10
|
||||
public val globalVariableWithGetter: kotlin.Int
|
||||
public val prop: kotlin.UByte = 255
|
||||
public fun takeNullableUInt(/*0*/ u: kotlin.UInt?): kotlin.Unit
|
||||
public fun takeUByte(/*0*/ u: kotlin.UByte): kotlin.Unit
|
||||
public fun takeUBytes(/*0*/ vararg u: kotlin.UByte /*kotlin.UByteArray*/): kotlin.Unit
|
||||
public fun takeUInt(/*0*/ u: kotlin.UInt): kotlin.Unit
|
||||
public fun takeULong(/*0*/ u: kotlin.ULong): kotlin.Unit
|
||||
public fun takeUShort(/*0*/ u: kotlin.UShort): kotlin.Unit
|
||||
public fun test(): kotlin.Unit
|
||||
public fun kotlin.Int.myPlus(/*0*/ other: kotlin.Int): kotlin.Int
|
||||
+15
@@ -100,5 +100,20 @@ public class DiagnosticsWithUnsignedTypesGenerated extends AbstractDiagnosticsWi
|
||||
public void testConversionOfSignedToUnsigned() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferenceForSignedAndUnsignedTypes.kt")
|
||||
public void testInferenceForSignedAndUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/inferenceForSignedAndUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("overloadResolutionForSignedAndUnsignedTypes.kt")
|
||||
public void testOverloadResolutionForSignedAndUnsignedTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/overloadResolutionForSignedAndUnsignedTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("signedToUnsignedConversionWithExpectedType.kt")
|
||||
public void testSignedToUnsignedConversionWithExpectedType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/signedToUnsignedConversionWithExpectedType.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -21860,6 +21860,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("signedToUnsignedLiteralConversion.kt")
|
||||
public void testSignedToUnsignedLiteralConversion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
|
||||
|
||||
+5
@@ -21860,6 +21860,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("signedToUnsignedLiteralConversion.kt")
|
||||
public void testSignedToUnsignedLiteralConversion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
|
||||
|
||||
+5
@@ -21860,6 +21860,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("signedToUnsignedLiteralConversion.kt")
|
||||
public void testSignedToUnsignedLiteralConversion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import kotlin.reflect.KClass
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
|
||||
enum class UnsignedType(val classId: ClassId) {
|
||||
@@ -28,6 +28,8 @@ object UnsignedTypes {
|
||||
val unsignedTypeNames = enumValues<UnsignedType>().map { it.typeName }.toSet()
|
||||
|
||||
fun isUnsignedType(type: KotlinType): Boolean {
|
||||
if (TypeUtils.noExpectedType(type)) return false
|
||||
|
||||
val descriptor = type.constructor.declarationDescriptor ?: return false
|
||||
return isUnsignedClass(descriptor)
|
||||
}
|
||||
|
||||
@@ -122,10 +122,28 @@ class UnsignedErrorValueTypeConstant(
|
||||
}
|
||||
|
||||
class IntegerValueTypeConstant(
|
||||
private val value: Number,
|
||||
module: ModuleDescriptor,
|
||||
override val parameters: CompileTimeConstant.Parameters
|
||||
private val value: Number,
|
||||
module: ModuleDescriptor,
|
||||
override val parameters: CompileTimeConstant.Parameters,
|
||||
val convertedFromSigned: Boolean = false
|
||||
) : CompileTimeConstant<Number> {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun IntegerValueTypeConstant.convertToUnsignedConstant(module: ModuleDescriptor): IntegerValueTypeConstant {
|
||||
val newParameters = CompileTimeConstant.Parameters(
|
||||
parameters.canBeUsedInAnnotation,
|
||||
parameters.isPure,
|
||||
isUnsignedNumberLiteral = true,
|
||||
isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral,
|
||||
usesVariableAsConstant = parameters.usesVariableAsConstant,
|
||||
usesNonConstValAsConstant = parameters.usesNonConstValAsConstant,
|
||||
isConvertableConstVal = parameters.isConvertableConstVal
|
||||
)
|
||||
|
||||
return IntegerValueTypeConstant(value, module, newParameters, convertedFromSigned = true)
|
||||
}
|
||||
}
|
||||
|
||||
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters)
|
||||
|
||||
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
|
||||
@@ -146,8 +164,8 @@ class IntegerValueTypeConstant(
|
||||
}
|
||||
|
||||
val unknownIntegerType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||
)
|
||||
|
||||
fun getType(expectedType: KotlinType): KotlinType = TypeUtils.getPrimitiveNumberType(typeConstructor, expectedType)
|
||||
|
||||
+5
@@ -19725,6 +19725,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("signedToUnsignedLiteralConversion.kt")
|
||||
public void testSignedToUnsignedLiteralConversion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedTypeValuesInsideStringTemplates.kt")
|
||||
public void testUnsignedTypeValuesInsideStringTemplates() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedTypeValuesInsideStringTemplates.kt");
|
||||
|
||||
+5
@@ -20775,6 +20775,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/iterateOverListOfBoxedUnsignedValues.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("signedToUnsignedLiteralConversion.kt")
|
||||
public void testSignedToUnsignedLiteralConversion() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unsignedTypeValuesInsideStringTemplates.kt")
|
||||
public void testUnsignedTypeValuesInsideStringTemplates() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedTypeValuesInsideStringTemplates.kt");
|
||||
|
||||
Reference in New Issue
Block a user