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 java.util.Collections;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.util.slicedMap.RewritePolicy.DO_NOTHING;
|
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 {
|
public interface BindingContext {
|
||||||
BindingContext EMPTY = new BindingContext() {
|
BindingContext EMPTY = new BindingContext() {
|
||||||
@@ -89,7 +90,7 @@ public interface BindingContext {
|
|||||||
|
|
||||||
WritableSlice<KtAnnotationEntry, AnnotationDescriptor> ANNOTATION = Slices.createSimpleSlice();
|
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> TYPE = Slices.createSimpleSlice();
|
||||||
WritableSlice<KtTypeReference, KotlinType> ABBREVIATED_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.FunctionTypesKt;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
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.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.name.SpecialNames;
|
import org.jetbrains.kotlin.name.SpecialNames;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.StatementFilter;
|
|
||||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
|
|
||||||
import org.jetbrains.kotlin.resolve.TypeResolver;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
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.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil;
|
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.IntegerValueTypeConstructor;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
||||||
@@ -69,6 +70,7 @@ public class ArgumentTypeResolver {
|
|||||||
@NotNull private final ReflectionTypes reflectionTypes;
|
@NotNull private final ReflectionTypes reflectionTypes;
|
||||||
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
@NotNull private final ConstantExpressionEvaluator constantExpressionEvaluator;
|
||||||
@NotNull private final FunctionPlaceholders functionPlaceholders;
|
@NotNull private final FunctionPlaceholders functionPlaceholders;
|
||||||
|
@NotNull private final ModuleDescriptor moduleDescriptor;
|
||||||
|
|
||||||
private ExpressionTypingServices expressionTypingServices;
|
private ExpressionTypingServices expressionTypingServices;
|
||||||
|
|
||||||
@@ -78,7 +80,8 @@ public class ArgumentTypeResolver {
|
|||||||
@NotNull KotlinBuiltIns builtIns,
|
@NotNull KotlinBuiltIns builtIns,
|
||||||
@NotNull ReflectionTypes reflectionTypes,
|
@NotNull ReflectionTypes reflectionTypes,
|
||||||
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
@NotNull ConstantExpressionEvaluator constantExpressionEvaluator,
|
||||||
@NotNull FunctionPlaceholders functionPlaceholders
|
@NotNull FunctionPlaceholders functionPlaceholders,
|
||||||
|
@NotNull ModuleDescriptor moduleDescriptor
|
||||||
) {
|
) {
|
||||||
this.typeResolver = typeResolver;
|
this.typeResolver = typeResolver;
|
||||||
this.doubleColonExpressionResolver = doubleColonExpressionResolver;
|
this.doubleColonExpressionResolver = doubleColonExpressionResolver;
|
||||||
@@ -86,6 +89,7 @@ public class ArgumentTypeResolver {
|
|||||||
this.reflectionTypes = reflectionTypes;
|
this.reflectionTypes = reflectionTypes;
|
||||||
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
this.constantExpressionEvaluator = constantExpressionEvaluator;
|
||||||
this.functionPlaceholders = functionPlaceholders;
|
this.functionPlaceholders = functionPlaceholders;
|
||||||
|
this.moduleDescriptor = moduleDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// component dependency cycle
|
// component dependency cycle
|
||||||
@@ -218,6 +222,11 @@ public class ArgumentTypeResolver {
|
|||||||
return expressionTypingServices.getTypeInfo(expression, newContext);
|
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());
|
KotlinTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
|
||||||
if (recordedTypeInfo != null) {
|
if (recordedTypeInfo != null) {
|
||||||
return recordedTypeInfo;
|
return recordedTypeInfo;
|
||||||
@@ -228,6 +237,28 @@ public class ArgumentTypeResolver {
|
|||||||
return expressionTypingServices.getTypeInfo(expression, newContext);
|
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
|
@NotNull
|
||||||
public KotlinTypeInfo getCallableReferenceTypeInfo(
|
public KotlinTypeInfo getCallableReferenceTypeInfo(
|
||||||
@NotNull KtExpression expression,
|
@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.smartcasts.DataFlowValueFactory
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
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.IntegerValueTypeConstructor
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer
|
||||||
@@ -309,9 +310,7 @@ class CallCompleter(
|
|||||||
|
|
||||||
private fun createTypeForConvertableConstant(constant: CompileTimeConstant<*>): SimpleType? {
|
private fun createTypeForConvertableConstant(constant: CompileTimeConstant<*>): SimpleType? {
|
||||||
val value = constant.getValue(TypeUtils.NO_EXPECTED_TYPE).safeAs<Number>()?.toLong() ?: return null
|
val value = constant.getValue(TypeUtils.NO_EXPECTED_TYPE).safeAs<Number>()?.toLong() ?: return null
|
||||||
val typeConstructor = IntegerValueTypeConstructor(
|
val typeConstructor = IntegerValueTypeConstructor(value, moduleDescriptor, constant.parameters)
|
||||||
value, moduleDescriptor, constant.parameters
|
|
||||||
)
|
|
||||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||||
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||||
@@ -332,11 +331,17 @@ class CallCompleter(
|
|||||||
var updatedType: KotlinType? = recordedType
|
var updatedType: KotlinType? = recordedType
|
||||||
|
|
||||||
val results = completeCallForArgument(deparenthesized, context)
|
val results = completeCallForArgument(deparenthesized, context)
|
||||||
|
|
||||||
if (results != null && results.isSingleResult) {
|
if (results != null && results.isSingleResult) {
|
||||||
val resolvedCall = results.resultingCall
|
val resolvedCall = results.resultingCall
|
||||||
updatedType = if (resolvedCall.hasInferredReturnType()) {
|
val constant = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized]
|
||||||
resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context)
|
if (constant !is IntegerValueTypeConstant || !constant.convertedFromSigned) {
|
||||||
} else null
|
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.),
|
// 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.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
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.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,17 +39,47 @@ public class Slices {
|
|||||||
@Override
|
@Override
|
||||||
public <K, V> boolean processRewrite(WritableSlice<K, V> slice, K key, V oldValue, V newValue) {
|
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)))) {
|
if (!((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue)))) {
|
||||||
// NOTE: Use BindingTraceContext.TRACK_REWRITES to debug this exception
|
logErrorAboutRewritingNonEqualObjects(slice, key, oldValue, newValue);
|
||||||
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) : ""));
|
|
||||||
}
|
}
|
||||||
return true;
|
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() {
|
private Slices() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,4 +151,13 @@ public class Slices {
|
|||||||
return new BasicWritableSlice<>(rewritePolicy);
|
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 {
|
public void testConversionOfSignedToUnsigned() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.kt");
|
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");
|
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")
|
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
|
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");
|
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")
|
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
|
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");
|
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")
|
@TestMetadata("unsignedLiteralsWithSignedOverflow.kt")
|
||||||
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
public void testUnsignedLiteralsWithSignedOverflow() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedLiteralsWithSignedOverflow.kt");
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import kotlin.reflect.KClass
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
|
|
||||||
enum class UnsignedType(val classId: ClassId) {
|
enum class UnsignedType(val classId: ClassId) {
|
||||||
@@ -28,6 +28,8 @@ object UnsignedTypes {
|
|||||||
val unsignedTypeNames = enumValues<UnsignedType>().map { it.typeName }.toSet()
|
val unsignedTypeNames = enumValues<UnsignedType>().map { it.typeName }.toSet()
|
||||||
|
|
||||||
fun isUnsignedType(type: KotlinType): Boolean {
|
fun isUnsignedType(type: KotlinType): Boolean {
|
||||||
|
if (TypeUtils.noExpectedType(type)) return false
|
||||||
|
|
||||||
val descriptor = type.constructor.declarationDescriptor ?: return false
|
val descriptor = type.constructor.declarationDescriptor ?: return false
|
||||||
return isUnsignedClass(descriptor)
|
return isUnsignedClass(descriptor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,10 +122,28 @@ class UnsignedErrorValueTypeConstant(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class IntegerValueTypeConstant(
|
class IntegerValueTypeConstant(
|
||||||
private val value: Number,
|
private val value: Number,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
override val parameters: CompileTimeConstant.Parameters
|
override val parameters: CompileTimeConstant.Parameters,
|
||||||
|
val convertedFromSigned: Boolean = false
|
||||||
) : CompileTimeConstant<Number> {
|
) : 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)
|
private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters)
|
||||||
|
|
||||||
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
|
override fun toConstantValue(expectedType: KotlinType): ConstantValue<Number> {
|
||||||
@@ -146,8 +164,8 @@ class IntegerValueTypeConstant(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val unknownIntegerType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
val unknownIntegerType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||||
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getType(expectedType: KotlinType): KotlinType = TypeUtils.getPrimitiveNumberType(typeConstructor, expectedType)
|
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");
|
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")
|
@TestMetadata("unsignedTypeValuesInsideStringTemplates.kt")
|
||||||
public void testUnsignedTypeValuesInsideStringTemplates() throws Exception {
|
public void testUnsignedTypeValuesInsideStringTemplates() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedTypeValuesInsideStringTemplates.kt");
|
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");
|
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")
|
@TestMetadata("unsignedTypeValuesInsideStringTemplates.kt")
|
||||||
public void testUnsignedTypeValuesInsideStringTemplates() throws Exception {
|
public void testUnsignedTypeValuesInsideStringTemplates() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedTypeValuesInsideStringTemplates.kt");
|
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedTypeValuesInsideStringTemplates.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user