From daadba09274994f92e438c6d859c68b2241245a4 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 28 Aug 2018 16:25:29 +0300 Subject: [PATCH] Postpone conversions from signed constants to unsigned ones #KT-26071 Fixed --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../kotlin/resolve/calls/CallCompleter.kt | 10 ++++++-- .../signedToUnsignedLiteralConversion.kt | 2 ++ .../inferenceForSignedAndUnsignedTypes.kt | 2 +- ...loadResolutionForSignedAndUnsignedTypes.kt | 2 +- ...nedToUnsignedConversionWithExpectedType.kt | 24 +++++++++---------- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 66ef73cf14d..7ef13f37302 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -911,6 +911,7 @@ public interface Errors { DiagnosticFactory1 NULL_FOR_NONNULL_TYPE = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 ILLEGAL_ESCAPE_SEQUENCE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED = DiagnosticFactory0.create(ERROR); // Casts and is-checks diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 568ac8bb72f..ba193cbc06a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -388,6 +388,7 @@ public class DefaultErrorMessages { MAP.put(NOT_A_CLASS, "Not a class"); MAP.put(ILLEGAL_ESCAPE_SEQUENCE, "Illegal escape sequence"); MAP.put(UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH, "Type of the constant expression cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath"); + MAP.put(SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED, "Conversion of signed constants to unsigned ones is prohibited"); MAP.put(RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS, "Left-hand side of callable reference matches expression syntax reserved for future releases"); 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 0e3ccceaef1..f77eeea9351 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallCompleter.kt @@ -11,6 +11,7 @@ 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.diagnostics.Errors import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER @@ -321,10 +322,15 @@ class CallCompleter( val results = completeCallForArgument(deparenthesized, context) + val constant = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized] + val convertedConst = constant is IntegerValueTypeConstant && constant.convertedFromSigned + if (convertedConst) { + context.trace.report(Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.on(deparenthesized)) + } + if (results != null && results.isSingleResult) { val resolvedCall = results.resultingCall - val constant = context.trace[BindingContext.COMPILE_TIME_VALUE, deparenthesized] - if (constant !is IntegerValueTypeConstant || !constant.convertedFromSigned) { + if (!convertedConst) { updatedType = if (resolvedCall.hasInferredReturnType()) resolvedCall.makeNullableTypeIfSafeReceiver(resolvedCall.resultingDescriptor?.returnType, context) diff --git a/compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt b/compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt index ccc985bd0cd..9e952666f02 100644 --- a/compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt +++ b/compiler/testData/codegen/box/unsignedTypes/signedToUnsignedLiteralConversion.kt @@ -1,6 +1,8 @@ // WITH_UNSIGNED // IGNORE_BACKEND: JS_IR, JVM_IR +@file:Suppress("SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED") + fun takeUByte(u: UByte) = u.toByte() fun takeUShort(u: UShort) = u.toShort() fun takeUInt(u: UInt) = u.toInt() diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/inferenceForSignedAndUnsignedTypes.kt b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/inferenceForSignedAndUnsignedTypes.kt index c3116fec67e..6608e406537 100644 --- a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/inferenceForSignedAndUnsignedTypes.kt +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/inferenceForSignedAndUnsignedTypes.kt @@ -13,5 +13,5 @@ fun foo() { takeUByte(id(1)) 1 + 1u - (1u + 1) checkType { _() } + (1u + 1) checkType { _() } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/overloadResolutionForSignedAndUnsignedTypes.kt b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/overloadResolutionForSignedAndUnsignedTypes.kt index 6a0b8b5136a..72c3331e2a4 100644 --- a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/overloadResolutionForSignedAndUnsignedTypes.kt +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/overloadResolutionForSignedAndUnsignedTypes.kt @@ -25,7 +25,7 @@ fun test() { foo(1) checkType { _() } foo(1u) checkType { _() } - foo(2147483648) checkType { _() } + foo(2147483648) checkType { _() } foo(2147483647 + 1) checkType { _() } fooByte(1) checkType { _() } diff --git a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/signedToUnsignedConversionWithExpectedType.kt b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/signedToUnsignedConversionWithExpectedType.kt index 4d59ea179cf..0bf938b9b4b 100644 --- a/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/signedToUnsignedConversionWithExpectedType.kt +++ b/compiler/testData/diagnostics/testsWithUnsignedTypes/conversions/signedToUnsignedConversionWithExpectedType.kt @@ -10,30 +10,30 @@ fun takeUBytes(vararg u: UByte) {} fun takeNullableUInt(u: UInt?) {} fun test() { - takeUInt(1 + 2) - takeUInt(1.plus(2)) - takeNullableUInt(4) + takeUInt(1 + 2) + takeUInt(1.plus(2)) + takeNullableUInt(4) takeUInt(Int.MAX_VALUE * 2L) - takeUInt(-1) + takeUInt(-1) takeUInt(Int.MAX_VALUE * 2L + 2) - takeUByte(1) - takeUByte(255) + takeUByte(1) + takeUByte(255) takeUByte(1.toByte()) - takeUShort(1) - takeUInt(1) - takeULong(1) + takeUShort(1) + takeUInt(1) + takeULong(1) takeULong(18446744073709551615) - takeULong(1844674407370955161) + takeULong(1844674407370955161) takeULong(18446744073709551615u) takeUInt(Int.MAX_VALUE * 2) - takeUInt(4294967294) + takeUInt(4294967294) - takeUBytes(1, 2, 255, 256, 0, -1, 40 + 2) + takeUBytes(1, 2, 255, 256, 0, -1, 40 + 2) takeUInt(1.myPlus(2))