From 0da3ae328e597af97933374d48576c68523ac5c3 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Mon, 28 May 2018 17:30:42 +0300 Subject: [PATCH] Handle case when `u`-literals are using without unsigned declarations --- .../jetbrains/kotlin/diagnostics/Errors.java | 2 + .../rendering/DefaultErrorMessages.java | 1 + .../evaluate/ConstantExpressionEvaluator.kt | 2 +- .../BasicExpressionTypingVisitor.java | 8 +++- ...ignedLiteralsWithoutArtifactOnClasspath.kt | 3 ++ ...gnedLiteralsWithoutArtifactOnClasspath.txt | 5 +++ .../checkers/DiagnosticsTestGenerated.java | 5 +++ .../DiagnosticsUsingJavacTestGenerated.java | 5 +++ .../resolve/constants/CompileTimeConstant.kt | 39 +++++++++++++++++-- .../constants/IntegerValueTypeConstructor.kt | 10 +++-- 10 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt create mode 100644 compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 014ef4a8e18..d420bae26de 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -885,6 +885,8 @@ public interface Errors { DiagnosticFactory1 ILLEGAL_ESCAPE = DiagnosticFactory1.create(ERROR, CUT_CHAR_QUOTES); 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); + // 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 e4eabd665b0..48a407d34b8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -382,6 +382,7 @@ public class DefaultErrorMessages { MAP.put(RESOLUTION_TO_CLASSIFIER, "{2}", NAME, TO_STRING, STRING); 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(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/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index ff92fb2f54d..2199ce2e6d3 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 @@ -935,7 +935,7 @@ private class ConstantExpressionEvaluatorVisitor( expectedType: KotlinType ): CompileTimeConstant<*>? { if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) { - return IntegerValueTypeConstant(value, constantExpressionEvaluator.module, parameters) + return createIntegerValueTypeConstant(value, constantExpressionEvaluator.module, parameters) } val integerValue = ConstantValueFactory.createIntegerConstantValue(value, expectedType, parameters.isUnsigned) if (integerValue != null) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index a8a49b31c3a..ab492ed5a6b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -206,7 +206,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { expression, context.trace, context.expectedType ); - if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) { + if (compileTimeConstant instanceof UnsignedErrorValueTypeConstant) { + ErrorValue.ErrorValueWithMessage value = ((UnsignedErrorValueTypeConstant) compileTimeConstant).getErrorValue(); + context.trace.report(Errors.UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH.on(expression)); + + return TypeInfoFactoryKt.createTypeInfo(value.getType(components.moduleDescriptor), context); + } + else if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) { CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context, components.moduleDescriptor, false); ConstantValue constantValue = compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null; diff --git a/compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt b/compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt new file mode 100644 index 00000000000..6cf80093333 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt @@ -0,0 +1,3 @@ +val u1 = 1u +val u2 = 0xFu +val u3 = 0b1u \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.txt b/compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.txt new file mode 100644 index 00000000000..1fd389d53fc --- /dev/null +++ b/compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.txt @@ -0,0 +1,5 @@ +package + +public val u1: [ERROR : Type cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath] +public val u2: [ERROR : Type cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath] +public val u3: [ERROR : Type cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath] diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 4443135ab9e..153e0f01c29 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10721,6 +10721,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inlineClasses/propertiesWithBackingFieldsInsideInlineClass.kt"); } + @TestMetadata("unsignedLiteralsWithoutArtifactOnClasspath.kt") + public void testUnsignedLiteralsWithoutArtifactOnClasspath() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt"); + } + @TestMetadata("varargsOnParametersOfInlineClassType.kt") public void testVarargsOnParametersOfInlineClassType() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 396fe938f9f..8ba970a92e7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10721,6 +10721,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inlineClasses/propertiesWithBackingFieldsInsideInlineClass.kt"); } + @TestMetadata("unsignedLiteralsWithoutArtifactOnClasspath.kt") + public void testUnsignedLiteralsWithoutArtifactOnClasspath() throws Exception { + runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt"); + } + @TestMetadata("varargsOnParametersOfInlineClassType.kt") public void testVarargsOnParametersOfInlineClassType() throws Exception { runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.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 8d7a734462c..c5a9ed3a7e8 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt @@ -19,10 +19,8 @@ package org.jetbrains.kotlin.resolve.constants import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies +import org.jetbrains.kotlin.types.* interface CompileTimeConstant { val isError: Boolean @@ -85,6 +83,39 @@ class TypedCompileTimeConstant( } } +fun createIntegerValueTypeConstant( + value: Number, + module: ModuleDescriptor, + parameters: CompileTimeConstant.Parameters +): CompileTimeConstant<*> { + return if (parameters.isUnsigned && !hasUnsignedTypesInModuleDependencies(module)) { + UnsignedErrorValueTypeConstant(value, parameters) + } else { + IntegerValueTypeConstant(value, module, parameters) + } +} + +fun hasUnsignedTypesInModuleDependencies(module: ModuleDescriptor): Boolean { + return module.findClassAcrossModuleDependencies(KotlinBuiltIns.FQ_NAMES.uInt) != null +} + +class UnsignedErrorValueTypeConstant( + private val value: Number, + override val parameters: CompileTimeConstant.Parameters +) : CompileTimeConstant { + val errorValue = ErrorValue.ErrorValueWithMessage( + "Type cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath" + ) + + override fun toConstantValue(expectedType: KotlinType): ConstantValue { + return errorValue + } + + override fun equals(other: Any?) = other is UnsignedErrorValueTypeConstant && value == other.value + + override fun hashCode() = value.hashCode() +} + class IntegerValueTypeConstant( private val value: Number, module: ModuleDescriptor, 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 3112201e2a5..d8fb3a7a98a 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/IntegerValueTypeConstructor.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.TypeConstructor @@ -40,6 +39,12 @@ class IntegerValueTypeConstructor( // for expected type 'Any' result type 'Int' should be returned val isUnsigned = parameters.isUnsigned + if (isUnsigned) { + assert(hasUnsignedTypesInModuleDependencies(module)) { + "Unsigned types should be on classpath to create an unsigned type constructor" + } + } + // TODO: fix value ranges for unsigned types checkBoundsAndAddSuperType( value, @@ -68,8 +73,7 @@ class IntegerValueTypeConstructor( } } - private fun unsignedType(classId: ClassId): SimpleType = - module.findClassAcrossModuleDependencies(classId)?.defaultType ?: ErrorUtils.createErrorType("Error type for $classId") + private fun unsignedType(classId: ClassId): SimpleType = module.findClassAcrossModuleDependencies(classId)!!.defaultType override fun getSupertypes(): Collection = supertypes