diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt index 822b5badd6c..6f191895f65 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnnotationUtil.kt @@ -31,6 +31,8 @@ val JVM_FIELD_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmField") val JVM_DEFAULT_FQ_NAME = FqName("kotlin.jvm.JvmDefault") +private val IMPLICIT_INTEGER_COERCION_ANNOTATION_FQ_NAME = FqName("kotlin.internal.ImplicitIntegerCoercion") + fun CallableMemberDescriptor.hasJvmDefaultAnnotation() = DescriptorUtils.getDirectMember(this).annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME) @@ -39,6 +41,10 @@ fun DeclarationDescriptor.hasJvmStaticAnnotation(): Boolean { return annotations.findAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) != null } +fun DeclarationDescriptor.hasImplicitIntegerCoercionAnnotation(): Boolean { + return annotations.findAnnotation(IMPLICIT_INTEGER_COERCION_ANNOTATION_FQ_NAME) != null +} + private val JVM_SYNTHETIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmSynthetic") fun DeclarationDescriptor.hasJvmSyntheticAnnotation() = findJvmSyntheticAnnotation() != null diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java index e0a6c2c5850..eb98195fb84 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ArgumentTypeResolver.java @@ -44,10 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil; import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.scopes.LexicalScope; -import org.jetbrains.kotlin.types.FunctionPlaceholders; -import org.jetbrains.kotlin.types.FunctionPlaceholdersKt; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeUtils; +import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.kotlin.types.expressions.*; import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt; @@ -392,9 +389,21 @@ public class ArgumentTypeResolver { @NotNull KtExpression expression ) { KotlinType type = trace.getType(expression); - if (type != null && !type.getConstructor().isDenotable()) { - if (type.getConstructor() instanceof IntegerValueTypeConstructor) { - IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) type.getConstructor(); + return type != null ? updateResultArgumentTypeIfNotDenotable(trace, statementFilter, expectedType, type, expression) : null; + } + + @Nullable + public KotlinType updateResultArgumentTypeIfNotDenotable( + @NotNull BindingTrace trace, + @NotNull StatementFilter statementFilter, + @NotNull KotlinType expectedType, + @NotNull KotlinType targetType, + @NotNull KtExpression expression + ) { + TypeConstructor typeConstructor = targetType.getConstructor(); + if (!typeConstructor.isDenotable()) { + if (typeConstructor instanceof IntegerValueTypeConstructor) { + IntegerValueTypeConstructor constructor = (IntegerValueTypeConstructor) typeConstructor; KotlinType primitiveType = TypeUtils.getPrimitiveNumberType(constructor, expectedType); constantExpressionEvaluator.updateNumberType(primitiveType, expression, statementFilter, trace); return primitiveType; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt index c325dbd30ef..c122efdd3f1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -20,9 +20,12 @@ import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.contracts.EffectSystem import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER +import org.jetbrains.kotlin.resolve.annotations.hasImplicitIntegerCoercionAnnotation import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable @@ -46,11 +49,11 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus 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.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant +import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.expressions.DataFlowAnalyzer +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.util.* class CallCompleter( @@ -279,28 +282,50 @@ class CallCompleter( for (valueArgument in context.call.valueArguments) { val argumentMapping = getArgumentMapping(valueArgument!!) - val (expectedType, callPosition) = when (argumentMapping) { - is ArgumentMatch -> Pair( - getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context), - CallPosition.ValueArgumentPosition(results.resultingCall, argumentMapping.valueParameter, valueArgument) - ) - else -> Pair(TypeUtils.NO_EXPECTED_TYPE, CallPosition.Unknown) + + val expectedType: KotlinType + val callPosition: CallPosition + val parameter: ValueParameterDescriptor? + when (argumentMapping) { + is ArgumentMatch -> { + expectedType = getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context) + callPosition = CallPosition.ValueArgumentPosition(results.resultingCall, argumentMapping.valueParameter, valueArgument) + parameter = argumentMapping.valueParameter + } + else -> { + expectedType = TypeUtils.NO_EXPECTED_TYPE + callPosition = CallPosition.Unknown + parameter = null + } } + val newContext = context.replaceDataFlowInfo(getDataFlowInfoForArgument(valueArgument)) .replaceExpectedType(expectedType) .replaceCallPosition(callPosition) - completeOneArgument(valueArgument, newContext) + completeOneArgument(valueArgument, parameter, newContext) } } + private fun createTypeForConvertableConstant(constant: CompileTimeConstant<*>): SimpleType? { + val value = constant.getValue(TypeUtils.NO_EXPECTED_TYPE).safeAs()?.toLong() ?: return null + val typeConstructor = IntegerValueTypeConstructor( + value, moduleDescriptor, constant.parameters + ) + return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( + Annotations.EMPTY, typeConstructor, emptyList(), false, + ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true) + ) + } + private fun completeOneArgument( - valueArgument: ValueArgument, + argument: ValueArgument, + parameter: ValueParameterDescriptor?, context: BasicCallResolutionContext ) { - if (valueArgument.isExternal()) return + if (argument.isExternal()) return - val expression = valueArgument.getArgumentExpression() ?: return + val expression = argument.getArgumentExpression() ?: return val deparenthesized = KtPsiUtil.getLastElementDeparenthesized(expression, context.statementFilter) ?: return val recordedType = context.trace.getType(expression) @@ -320,6 +345,18 @@ class CallCompleter( updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression) ?: updatedType } + if (parameter?.hasImplicitIntegerCoercionAnnotation() == true) { + val argumentCompileTimeValue = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized] + if (argumentCompileTimeValue != null && argumentCompileTimeValue.parameters.isConvertableConstVal) { + val generalNumberType = createTypeForConvertableConstant(argumentCompileTimeValue) + if (generalNumberType != null) { + updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable( + context.trace, context.statementFilter, context.expectedType, generalNumberType, expression + ) + } + } + } + updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context.statementFilter, context.trace) // While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 26dde803f2f..9d6e793d5a4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.BindingContext.COLLECTION_LITERAL_CALL +import org.jetbrains.kotlin.resolve.annotations.hasImplicitIntegerCoercionAnnotation import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall @@ -401,7 +402,8 @@ private class ConstantExpressionEvaluatorVisitor( isUnsignedNumberLiteral = isUnsigned, isUnsignedLongNumberLiteral = isUnsignedLong, usesVariableAsConstant = false, - usesNonConstValAsConstant = false + usesNonConstValAsConstant = false, + isConvertableConstVal = false ) ) } @@ -450,7 +452,8 @@ private class ConstantExpressionEvaluatorVisitor( isUnsignedLongNumberLiteral = false, canBeUsedInAnnotation = canBeUsedInAnnotation, usesVariableAsConstant = usesVariableAsConstant, - usesNonConstValAsConstant = usesNonConstantVariableAsConstant + usesNonConstValAsConstant = usesNonConstantVariableAsConstant, + isConvertableConstVal = false ) ) else null @@ -513,7 +516,8 @@ private class ConstantExpressionEvaluatorVisitor( isUnsignedNumberLiteral = false, isUnsignedLongNumberLiteral = false, usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant, - usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant + usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant, + isConvertableConstVal = false ) ) } else { @@ -560,7 +564,8 @@ private class ConstantExpressionEvaluatorVisitor( canBeUsedInAnnotation, !isNumberConversionMethod && isArgumentPure, false, false, - usesVariableAsConstant, usesNonConstValAsConstant + usesVariableAsConstant, usesNonConstValAsConstant, + false ) ) } else if (argumentsEntrySet.size == 1) { @@ -592,7 +597,7 @@ private class ConstantExpressionEvaluatorVisitor( val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression) val parameters = CompileTimeConstant.Parameters( - canBeUsedInAnnotation, areArgumentsPure, false, false, usesVariableAsConstant, usesNonConstValAsConstant + canBeUsedInAnnotation, areArgumentsPure, false, false, usesVariableAsConstant, usesNonConstValAsConstant, false ) return when (resultingDescriptorName) { OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters) @@ -705,6 +710,11 @@ private class ConstantExpressionEvaluatorVisitor( // TODO: FIXME: see KT-10425 if (callableDescriptor is PropertyDescriptor && callableDescriptor.modality != Modality.FINAL) return null + val isConvertableConstVal = + callableDescriptor.isConst && + callableDescriptor.hasImplicitIntegerCoercionAnnotation() && + callableDescriptor.compileTimeInitializer is IntValue + return callableDescriptor.compileTimeInitializer?.wrap( CompileTimeConstant.Parameters( canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor), @@ -712,7 +722,8 @@ private class ConstantExpressionEvaluatorVisitor( isUnsignedNumberLiteral = false, isUnsignedLongNumberLiteral = false, usesVariableAsConstant = true, - usesNonConstValAsConstant = !callableDescriptor.isConst + usesNonConstValAsConstant = !callableDescriptor.isConst, + isConvertableConstVal = isConvertableConstVal ) ) } @@ -973,11 +984,18 @@ private class ConstantExpressionEvaluatorVisitor( isUnsigned: Boolean = false, isUnsignedLong: Boolean = false, usesVariableAsConstant: Boolean = false, - usesNonConstValAsConstant: Boolean = false + usesNonConstValAsConstant: Boolean = false, + isConvertableConstVal: Boolean = false ): TypedCompileTimeConstant = wrap( CompileTimeConstant.Parameters( - canBeUsedInAnnotation, isPure, isUnsigned, isUnsignedLong, usesVariableAsConstant, usesNonConstValAsConstant + canBeUsedInAnnotation, + isPure, + isUnsigned, + isUnsignedLong, + usesVariableAsConstant, + usesNonConstValAsConstant, + isConvertableConstVal ) ) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index 895422b060b..232225a20bc 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -251,6 +251,10 @@ class InsertImplicitCasts(context: GeneratorContext) : IrElementTransformerVoid( KotlinBuiltIns.isByte(this) || KotlinBuiltIns.isShort(this) || KotlinBuiltIns.isInt(this) || - KotlinBuiltIns.isLong(this) + KotlinBuiltIns.isLong(this) || + KotlinBuiltIns.isUByte(this) || + KotlinBuiltIns.isUShort(this) || + KotlinBuiltIns.isUInt(this) || + KotlinBuiltIns.isULong(this) } diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.kt b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.kt new file mode 100644 index 00000000000..6387689f38b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.kt @@ -0,0 +1,68 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +// FILE: annotation.kt + +package kotlin.internal + +annotation class ImplicitIntegerCoercion + +// FILE: test.kt + +import kotlin.internal.ImplicitIntegerCoercion + +@ImplicitIntegerCoercion +const val IMPLICIT_INT = 255 + +@ImplicitIntegerCoercion +const val EXPLICIT_INT: Int = 255 + +@ImplicitIntegerCoercion +const val LONG_CONST = 255L + +@ImplicitIntegerCoercion +val NON_CONST = 255 + +@ImplicitIntegerCoercion +const val BIGGER_THAN_UBYTE = 256 + +@ImplicitIntegerCoercion +const val UINT_CONST = 42u + +fun takeUByte(@ImplicitIntegerCoercion u: UByte) {} +fun takeUShort(@ImplicitIntegerCoercion u: UShort) {} +fun takeUInt(@ImplicitIntegerCoercion u: UInt) {} +fun takeULong(@ImplicitIntegerCoercion u: ULong) {} + +fun takeUBytes(@ImplicitIntegerCoercion vararg u: UByte) {} + +fun takeLong(@ImplicitIntegerCoercion l: Long) {} + +fun takeUIntWithoutAnnotaion(u: UInt) {} + +fun takeIntWithoutAnnotation(i: Int) {} + +fun test() { + takeUByte(IMPLICIT_INT) + takeUByte(EXPLICIT_INT) + + takeUShort(IMPLICIT_INT) + takeUShort(BIGGER_THAN_UBYTE) + + takeUInt(IMPLICIT_INT) + + takeULong(IMPLICIT_INT) + + takeUBytes(IMPLICIT_INT, EXPLICIT_INT, 42u) + + takeLong(IMPLICIT_INT) + + takeIntWithoutAnnotation(IMPLICIT_INT) + + takeUIntWithoutAnnotaion(UINT_CONST) + + takeUByte(LONG_CONST) + takeUByte(NON_CONST) + takeUByte(BIGGER_THAN_UBYTE) + takeUByte(UINT_CONST) + takeUIntWithoutAnnotaion(IMPLICIT_INT) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.txt b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.txt new file mode 100644 index 00000000000..fbd265cd440 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.txt @@ -0,0 +1,303 @@ +package + +@kotlin.internal.ImplicitIntegerCoercion public const val BIGGER_THAN_UBYTE: kotlin.Int = 256 +@kotlin.internal.ImplicitIntegerCoercion public const val EXPLICIT_INT: kotlin.Int = 255 +@kotlin.internal.ImplicitIntegerCoercion public const val IMPLICIT_INT: kotlin.Int = 255 +@kotlin.internal.ImplicitIntegerCoercion public const val LONG_CONST: kotlin.Long = 255.toLong() +@kotlin.internal.ImplicitIntegerCoercion public val NON_CONST: kotlin.Int = 255 +@kotlin.internal.ImplicitIntegerCoercion public const val UINT_CONST: kotlin.UInt = 42.toUInt() +public fun takeIntWithoutAnnotation(/*0*/ i: kotlin.Int): kotlin.Unit +public fun takeLong(/*0*/ @kotlin.internal.ImplicitIntegerCoercion l: kotlin.Long): kotlin.Unit +public fun takeUByte(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.UByte): kotlin.Unit +public fun takeUBytes(/*0*/ @kotlin.internal.ImplicitIntegerCoercion vararg u: kotlin.UByte /*kotlin.UByteArray*/): kotlin.Unit +public fun takeUInt(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.UInt): kotlin.Unit +public fun takeUIntWithoutAnnotaion(/*0*/ u: kotlin.UInt): kotlin.Unit +public fun takeULong(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.ULong): kotlin.Unit +public fun takeUShort(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.UShort): kotlin.Unit +public fun test(): kotlin.Unit + +package kotlin { + + package kotlin.annotation { + } + + package kotlin.collections { + } + + package kotlin.comparisons { + } + + package kotlin.concurrent { + } + + package kotlin.coroutines { + + package kotlin.coroutines.experimental { + + package kotlin.coroutines.experimental.intrinsics { + } + + package kotlin.coroutines.experimental.jvm { + + package kotlin.coroutines.experimental.jvm.internal { + } + } + } + } + + package kotlin.experimental { + } + + package kotlin.internal { + + public final annotation class ImplicitIntegerCoercion : kotlin.Annotation { + public constructor ImplicitIntegerCoercion() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + package kotlin.internal.contracts { + } + } + + package kotlin.io { + } + + package kotlin.jvm { + + package kotlin.jvm.functions { + } + + package kotlin.jvm.internal { + + package kotlin.jvm.internal.markers { + } + + package kotlin.jvm.internal.unsafe { + } + } + } + + package kotlin.math { + } + + package kotlin.properties { + } + + package kotlin.ranges { + } + + package kotlin.reflect { + + package kotlin.reflect.full { + } + + package kotlin.reflect.jvm { + + package kotlin.reflect.jvm.internal { + + package kotlin.reflect.jvm.internal.components { + } + + package kotlin.reflect.jvm.internal.impl { + + package kotlin.reflect.jvm.internal.impl.builtins { + + package kotlin.reflect.jvm.internal.impl.builtins.functions { + } + + package kotlin.reflect.jvm.internal.impl.builtins.jvm { + } + } + + package kotlin.reflect.jvm.internal.impl.descriptors { + + package kotlin.reflect.jvm.internal.impl.descriptors.annotations { + } + + package kotlin.reflect.jvm.internal.impl.descriptors.deserialization { + } + + package kotlin.reflect.jvm.internal.impl.descriptors.impl { + } + } + + package kotlin.reflect.jvm.internal.impl.incremental { + + package kotlin.reflect.jvm.internal.impl.incremental.components { + } + } + + package kotlin.reflect.jvm.internal.impl.load { + + package kotlin.reflect.jvm.internal.impl.load.java { + + package kotlin.reflect.jvm.internal.impl.load.java.components { + } + + package kotlin.reflect.jvm.internal.impl.load.java.descriptors { + } + + package kotlin.reflect.jvm.internal.impl.load.java.lazy { + + package kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors { + } + + package kotlin.reflect.jvm.internal.impl.load.java.lazy.types { + } + } + + package kotlin.reflect.jvm.internal.impl.load.java.sources { + } + + package kotlin.reflect.jvm.internal.impl.load.java.structure { + } + + package kotlin.reflect.jvm.internal.impl.load.java.typeEnhancement { + } + } + + package kotlin.reflect.jvm.internal.impl.load.kotlin { + + package kotlin.reflect.jvm.internal.impl.load.kotlin.header { + } + } + } + + package kotlin.reflect.jvm.internal.impl.metadata { + + package kotlin.reflect.jvm.internal.impl.metadata.builtins { + } + + package kotlin.reflect.jvm.internal.impl.metadata.deserialization { + } + + package kotlin.reflect.jvm.internal.impl.metadata.jvm { + + package kotlin.reflect.jvm.internal.impl.metadata.jvm.deserialization { + } + } + } + + package kotlin.reflect.jvm.internal.impl.name { + } + + package kotlin.reflect.jvm.internal.impl.protobuf { + } + + package kotlin.reflect.jvm.internal.impl.renderer { + } + + package kotlin.reflect.jvm.internal.impl.resolve { + + package kotlin.reflect.jvm.internal.impl.resolve.calls { + + package kotlin.reflect.jvm.internal.impl.resolve.calls.inference { + } + } + + package kotlin.reflect.jvm.internal.impl.resolve.constants { + } + + package kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil { + } + + package kotlin.reflect.jvm.internal.impl.resolve.jvm { + } + + package kotlin.reflect.jvm.internal.impl.resolve.scopes { + + package kotlin.reflect.jvm.internal.impl.resolve.scopes.receivers { + } + } + } + + package kotlin.reflect.jvm.internal.impl.serialization { + + package kotlin.reflect.jvm.internal.impl.serialization.deserialization { + + package kotlin.reflect.jvm.internal.impl.serialization.deserialization.builtins { + } + + package kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors { + } + } + } + + package kotlin.reflect.jvm.internal.impl.storage { + } + + package kotlin.reflect.jvm.internal.impl.types { + + package kotlin.reflect.jvm.internal.impl.types.checker { + } + + package kotlin.reflect.jvm.internal.impl.types.error { + } + + package kotlin.reflect.jvm.internal.impl.types.typeUtil { + } + + package kotlin.reflect.jvm.internal.impl.types.typesApproximation { + } + } + + package kotlin.reflect.jvm.internal.impl.util { + + package kotlin.reflect.jvm.internal.impl.util.capitalizeDecapitalize { + } + + package kotlin.reflect.jvm.internal.impl.util.collectionUtils { + } + } + + package kotlin.reflect.jvm.internal.impl.utils { + } + } + + package kotlin.reflect.jvm.internal.pcollections { + } + + package kotlin.reflect.jvm.internal.structure { + } + } + } + } + + package kotlin.script { + + package kotlin.script.dependencies { + } + + package kotlin.script.experimental { + + package kotlin.script.experimental.dependencies { + } + + package kotlin.script.experimental.location { + } + } + + package kotlin.script.extensions { + } + + package kotlin.script.templates { + + package kotlin.script.templates.standard { + } + } + } + + package kotlin.sequences { + } + + package kotlin.system { + } + + package kotlin.test { + } + + package kotlin.text { + } +} diff --git a/compiler/testData/ir/irText/expressions/signedToUnsignedConversions.kt b/compiler/testData/ir/irText/expressions/signedToUnsignedConversions.kt new file mode 100644 index 00000000000..b886fb1ac4e --- /dev/null +++ b/compiler/testData/ir/irText/expressions/signedToUnsignedConversions.kt @@ -0,0 +1,54 @@ +// WITH_UNSIGNED + +// FILE: signedToUnsignedConversions_annotation.kt + +package kotlin.internal + +annotation class ImplicitIntegerCoercion + +// FILE: signedToUnsignedConversions_test.kt + +import kotlin.internal.ImplicitIntegerCoercion + +@ImplicitIntegerCoercion +const val IMPLICIT_INT = 255 + +@ImplicitIntegerCoercion +const val EXPLICIT_INT: Int = 255 + +@ImplicitIntegerCoercion +const val LONG_CONST = 255L + +@ImplicitIntegerCoercion +val NON_CONST = 255 + +@ImplicitIntegerCoercion +const val BIGGER_THAN_UBYTE = 256 + +@ImplicitIntegerCoercion +const val UINT_CONST = 42u + +fun takeUByte(@ImplicitIntegerCoercion u: UByte) {} +fun takeUShort(@ImplicitIntegerCoercion u: UShort) {} +fun takeUInt(@ImplicitIntegerCoercion u: UInt) {} +fun takeULong(@ImplicitIntegerCoercion u: ULong) {} + +fun takeUBytes(@ImplicitIntegerCoercion vararg u: UByte) {} + +fun takeLong(@ImplicitIntegerCoercion l: Long) {} + +fun test() { + takeUByte(IMPLICIT_INT) + takeUByte(EXPLICIT_INT) + + takeUShort(IMPLICIT_INT) + takeUShort(BIGGER_THAN_UBYTE) + + takeUInt(IMPLICIT_INT) + + takeULong(IMPLICIT_INT) + + takeUBytes(IMPLICIT_INT, EXPLICIT_INT, 42u) + + takeLong(IMPLICIT_INT) +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/signedToUnsignedConversions_annotation.txt b/compiler/testData/ir/irText/expressions/signedToUnsignedConversions_annotation.txt new file mode 100644 index 00000000000..33fdae06a65 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/signedToUnsignedConversions_annotation.txt @@ -0,0 +1,17 @@ +FILE fqName:kotlin.internal fileName:/signedToUnsignedConversions_annotation.kt + CLASS ANNOTATION_CLASS name:ImplicitIntegerCoercion modality:FINAL visibility:public flags: superTypes:[kotlin.Annotation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:kotlin.internal.ImplicitIntegerCoercion flags: + CONSTRUCTOR visibility:public <> () returnType:kotlin.internal.ImplicitIntegerCoercion flags:primary + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + overridden: + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + overridden: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + overridden: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: diff --git a/compiler/testData/ir/irText/expressions/signedToUnsignedConversions_test.txt b/compiler/testData/ir/irText/expressions/signedToUnsignedConversions_test.txt new file mode 100644 index 00000000000..cbfc593839a --- /dev/null +++ b/compiler/testData/ir/irText/expressions/signedToUnsignedConversions_test.txt @@ -0,0 +1,136 @@ +FILE fqName: fileName:/signedToUnsignedConversions_test.kt + PROPERTY name:IMPLICIT_INT visibility:public modality:FINAL flags:const,val + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + FIELD PROPERTY_BACKING_FIELD name:IMPLICIT_INT type:kotlin.Int visibility:public flags:final + EXPRESSION_BODY + CONST Int type=kotlin.Int value=255 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int flags: + correspondingProperty: PROPERTY name:IMPLICIT_INT visibility:public modality:FINAL flags:const,val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'IMPLICIT_INT: Int' type=kotlin.Int origin=null + PROPERTY name:EXPLICIT_INT visibility:public modality:FINAL flags:const,val + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + FIELD PROPERTY_BACKING_FIELD name:EXPLICIT_INT type:kotlin.Int visibility:public flags:final + EXPRESSION_BODY + CONST Int type=kotlin.Int value=255 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int flags: + correspondingProperty: PROPERTY name:EXPLICIT_INT visibility:public modality:FINAL flags:const,val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'EXPLICIT_INT: Int' type=kotlin.Int origin=null + PROPERTY name:LONG_CONST visibility:public modality:FINAL flags:const,val + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + FIELD PROPERTY_BACKING_FIELD name:LONG_CONST type:kotlin.Long visibility:public flags:final + EXPRESSION_BODY + CONST Long type=kotlin.Long value=255 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Long flags: + correspondingProperty: PROPERTY name:LONG_CONST visibility:public modality:FINAL flags:const,val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Long' + GET_FIELD 'LONG_CONST: Long' type=kotlin.Long origin=null + PROPERTY name:NON_CONST visibility:public modality:FINAL flags:val + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + FIELD PROPERTY_BACKING_FIELD name:NON_CONST type:kotlin.Int visibility:public flags:final + EXPRESSION_BODY + CONST Int type=kotlin.Int value=255 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int flags: + correspondingProperty: PROPERTY name:NON_CONST visibility:public modality:FINAL flags:val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'NON_CONST: Int' type=kotlin.Int origin=null + PROPERTY name:BIGGER_THAN_UBYTE visibility:public modality:FINAL flags:const,val + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + FIELD PROPERTY_BACKING_FIELD name:BIGGER_THAN_UBYTE type:kotlin.Int visibility:public flags:final + EXPRESSION_BODY + CONST Int type=kotlin.Int value=256 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int flags: + correspondingProperty: PROPERTY name:BIGGER_THAN_UBYTE visibility:public modality:FINAL flags:const,val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'BIGGER_THAN_UBYTE: Int' type=kotlin.Int origin=null + PROPERTY name:UINT_CONST visibility:public modality:FINAL flags:const,val + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + FIELD PROPERTY_BACKING_FIELD name:UINT_CONST type:kotlin.UInt visibility:public flags:final + EXPRESSION_BODY + CONST Int type=kotlin.UInt value=42 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.UInt flags: + correspondingProperty: PROPERTY name:UINT_CONST visibility:public modality:FINAL flags:const,val + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): UInt' + GET_FIELD 'UINT_CONST: UInt' type=kotlin.UInt origin=null + FUN name:takeUByte visibility:public modality:FINAL <> (u:kotlin.UByte) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:u index:0 type:kotlin.UByte flags: + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + BLOCK_BODY + FUN name:takeUShort visibility:public modality:FINAL <> (u:kotlin.UShort) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:u index:0 type:kotlin.UShort flags: + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + BLOCK_BODY + FUN name:takeUInt visibility:public modality:FINAL <> (u:kotlin.UInt) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:u index:0 type:kotlin.UInt flags: + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + BLOCK_BODY + FUN name:takeULong visibility:public modality:FINAL <> (u:kotlin.ULong) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:u index:0 type:kotlin.ULong flags: + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + BLOCK_BODY + FUN name:takeUBytes visibility:public modality:FINAL <> (u:kotlin.UByteArray) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:u index:0 type:kotlin.UByteArray varargElementType:kotlin.UByte flags:vararg + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + BLOCK_BODY + FUN name:takeLong visibility:public modality:FINAL <> (l:kotlin.Long) returnType:kotlin.Unit flags: + VALUE_PARAMETER name:l index:0 type:kotlin.Long flags: + annotations: + CALL 'constructor ImplicitIntegerCoercion()' type=kotlin.internal.ImplicitIntegerCoercion origin=null + BLOCK_BODY + FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit flags: + BLOCK_BODY + CALL 'takeUByte(UByte): Unit' type=kotlin.Unit origin=null + u: TYPE_OP type=kotlin.UByte origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UByte + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UByte modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CALL 'takeUByte(UByte): Unit' type=kotlin.Unit origin=null + u: TYPE_OP type=kotlin.UByte origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UByte + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UByte modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CALL 'takeUShort(UShort): Unit' type=kotlin.Unit origin=null + u: TYPE_OP type=kotlin.UShort origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UShort + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UShort modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CALL 'takeUShort(UShort): Unit' type=kotlin.Unit origin=null + u: TYPE_OP type=kotlin.UShort origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UShort + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UShort modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CALL 'takeUInt(UInt): Unit' type=kotlin.Unit origin=null + u: TYPE_OP type=kotlin.UInt origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UInt + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UInt modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CALL 'takeULong(ULong): Unit' type=kotlin.Unit origin=null + u: TYPE_OP type=kotlin.ULong origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.ULong + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:ULong modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CALL 'takeUBytes(vararg UByte): Unit' type=kotlin.Unit origin=null + u: VARARG type=kotlin.UByteArray varargElementType=kotlin.UByte + TYPE_OP type=kotlin.UByte origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UByte + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UByte modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + TYPE_OP type=kotlin.UByte origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.UByte + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:UByte modality:FINAL visibility:public flags: superTypes:[kotlin.Comparable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY + CONST Byte type=kotlin.UByte value=42 + CALL 'takeLong(Long): Unit' type=kotlin.Unit origin=null + l: TYPE_OP type=kotlin.Long origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Long + typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Long modality:FINAL visibility:public flags: superTypes:[kotlin.Number; kotlin.Comparable; java.io.Serializable] + CALL '(): Int' type=kotlin.Int origin=GET_PROPERTY diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/constraintSystem/ConstraintSystemTestData.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/constraintSystem/ConstraintSystemTestData.kt index aed24c44a32..18ba9b00dfb 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/constraintSystem/ConstraintSystemTestData.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/constraintSystem/ConstraintSystemTestData.kt @@ -66,7 +66,7 @@ class ConstraintSystemTestData( val matcher = INTEGER_VALUE_TYPE_PATTERN.matcher(name) if (matcher.find()) { val number = matcher.group(1)!! - val parameters = CompileTimeConstant.Parameters(false, false, false, false, false, false) + val parameters = CompileTimeConstant.Parameters(false, false, false, false, false, false, false) return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( Annotations.EMPTY, IntegerValueTypeConstructor(number.toLong(), functionFoo.module, parameters), diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java index d61a2778c40..b37c3714548 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithUnsignedTypesGenerated.java @@ -83,4 +83,22 @@ public class DiagnosticsWithUnsignedTypesGenerated extends AbstractDiagnosticsWi public void testWrongLongSuffixForULong() throws Exception { runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/wrongLongSuffixForULong.kt"); } + + @TestMetadata("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Conversions extends AbstractDiagnosticsWithUnsignedTypes { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInConversions() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("conversionOfSignedToUnsigned.kt") + public void testConversionOfSignedToUnsigned() throws Exception { + runTest("compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/conversionOfSignedToUnsigned.kt"); + } + } } diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index fecffb6e47b..22ce50d1118 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1032,6 +1032,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/setFieldWithImplicitCast.kt"); } + @TestMetadata("signedToUnsignedConversions.kt") + public void testSignedToUnsignedConversions() throws Exception { + runTest("compiler/testData/ir/irText/expressions/signedToUnsignedConversions.kt"); + } + @TestMetadata("simpleOperators.kt") public void testSimpleOperators() throws Exception { runTest("compiler/testData/ir/irText/expressions/simpleOperators.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt index 378d2fd041a..0043a7ba9e0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt @@ -50,7 +50,9 @@ interface CompileTimeConstant { // `isUnsignedLongNumberLiteral` means that this constant represents simple number literal with `{uU}{lL}` suffix (123uL, 0xFEUL) val isUnsignedLongNumberLiteral: Boolean, val usesVariableAsConstant: Boolean, - val usesNonConstValAsConstant: Boolean + val usesNonConstValAsConstant: Boolean, + // `isConvertableConstVal` means that this is `const val` that has `ImplicitIntegerCoercion` annotation + val isConvertableConstVal: Boolean ) override fun equals(other: Any?): Boolean diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt index 1bc60136b10..cdfd0c76945 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt @@ -39,17 +39,38 @@ class IntegerValueTypeConstructor( // 'getPrimitiveNumberType' returns first of supertypes that is a subtype of expected type // for expected type 'Any' result type 'Int' should be returned val isUnsigned = parameters.isUnsignedNumberLiteral + val isConvertable = parameters.isConvertableConstVal - if (isUnsigned) { + if (isUnsigned || isConvertable) { assert(hasUnsignedTypesInModuleDependencies(module)) { "Unsigned types should be on classpath to create an unsigned type constructor" } } - checkBoundsAndAddSuperType(value, if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uInt) else builtIns.intType) - checkBoundsAndAddSuperType(value, if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uByte) else builtIns.byteType) - checkBoundsAndAddSuperType(value, if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uShort) else builtIns.shortType) - supertypes.add(if (isUnsigned) unsignedType(KotlinBuiltIns.FQ_NAMES.uLong) else builtIns.longType) + when { + isConvertable -> { + addSignedSuperTypes() + addUnsignedSuperTypes() + } + + isUnsigned -> addUnsignedSuperTypes() + + else -> addSignedSuperTypes() + } + } + + private fun addSignedSuperTypes() { + checkBoundsAndAddSuperType(value, builtIns.intType) + checkBoundsAndAddSuperType(value, builtIns.byteType) + checkBoundsAndAddSuperType(value, builtIns.shortType) + supertypes.add(builtIns.longType) + } + + private fun addUnsignedSuperTypes() { + checkBoundsAndAddSuperType(value, unsignedType(KotlinBuiltIns.FQ_NAMES.uInt)) + checkBoundsAndAddSuperType(value, unsignedType(KotlinBuiltIns.FQ_NAMES.uByte)) + checkBoundsAndAddSuperType(value, unsignedType(KotlinBuiltIns.FQ_NAMES.uShort)) + supertypes.add(unsignedType(KotlinBuiltIns.FQ_NAMES.uLong)) } private fun checkBoundsAndAddSuperType(value: Long, kotlinType: KotlinType) {