diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt index 887129d56a1..f0c36ef4c5a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -181,9 +181,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentsEntrySet = resolvedCall.getValueArguments().entrySet() if (argumentsEntrySet.isEmpty()) { val result = evaluateUnaryAndCheck(argumentForReceiver, resultingDescriptorName.asString(), callExpression) - val isArgumentPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForReceiver.expression) - val isNumberConventionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS - return createCompileTimeConstant(result, fullExpression, expectedType, !isNumberConventionMethod && isArgumentPure ?: false) + val isArgumentPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForReceiver.expression) ?: false + val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS + return createCompileTimeConstant(result, fullExpression, expectedType, !isNumberConversionMethod && isArgumentPure) } else if (argumentsEntrySet.size() == 1) { val (parameter, argument) = argumentsEntrySet.first() @@ -300,13 +300,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return evaluateCall(expression, calleeExpression, receiverExpression, expectedType) } - // Mynum.A + // MyEnum.A, Integer.MAX_VALUE if (selectorExpression != null) { - val compileTimeConstant = evaluate(selectorExpression, expectedType) - if (compileTimeConstant != null) { - trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true); - } - return compileTimeConstant + return evaluate(selectorExpression, expectedType) } return null @@ -364,7 +360,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return null } - private class OperationArgument(val value: Any, val ctcType: CompileTimeType<*>, val expression: JetExpression) private fun createOperationArgumentForReceiver(resolvedCall: ResolvedCall<*>, expression: JetExpression): OperationArgument? { @@ -374,17 +369,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val receiverCompileTimeType = getCompileTimeType(receiverExpressionType) if (receiverCompileTimeType == null) return null - val receiverValue = evaluate(expression, receiverExpressionType)?.getValue() - if (receiverValue == null) return null - - if (receiverValue is NumberValueTypeConstructor<*>) { - val newValue = receiverValue.getValueForNumberType(receiverExpressionType) - if (newValue != null) { - return OperationArgument(newValue, receiverCompileTimeType, expression) - } - } - - return OperationArgument(receiverValue, receiverCompileTimeType, expression) + return createOperationArgument(expression, receiverExpressionType, receiverCompileTimeType) } private fun createOperationArgumentForFirstParameter(argument: ResolvedValueArgument, parameter: ValueParameterDescriptor): OperationArgument? { @@ -397,20 +382,21 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val argumentExpression = arguments.first().getArgumentExpression() if (argumentExpression == null) return null - val constant = evaluate(argumentExpression, parameter.getType()) - if (constant == null) return null + return createOperationArgument(argumentExpression, parameter.getType(), argumentCompileTimeType) + } - val argumentValue = constant.getValue() - if (argumentValue == null) return null + private fun createOperationArgument(expression: JetExpression, expressionType: JetType, compileTimeType: CompileTimeType<*>): OperationArgument? { + val evaluationResult = evaluate(expression, expressionType)?.getValue() + if (evaluationResult == null) return null - if (argumentValue is NumberValueTypeConstructor<*>) { - val newValue = argumentValue.getValueForNumberType(parameter.getType()) - if (newValue != null) { - return OperationArgument(newValue, argumentCompileTimeType, argumentExpression) + if (evaluationResult is NumberValueTypeConstructor<*>) { + val evaluationResultWithNewType = evaluationResult.getValueForNumberType(expressionType) + if (evaluationResultWithNewType != null) { + return OperationArgument(evaluationResultWithNewType, compileTimeType, expression) } } - return OperationArgument(argumentValue, argumentCompileTimeType, argumentExpression) + return OperationArgument(evaluationResult, compileTimeType, expression) } fun createCompileTimeConstant(value: Any?, expression: JetExpression, expectedType: JetType?, isPure: Boolean = true): CompileTimeConstant<*>? { diff --git a/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueByte.kt b/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueByte.kt index 41d9cc7ac02..c927a96f218 100644 --- a/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueByte.kt +++ b/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueByte.kt @@ -5,7 +5,6 @@ Retention(RetentionPolicy.RUNTIME) annotation class Ann( val p1: Int, val p2: Byte, - val p3: Byte, val p4: Int, val p5: Int ) @@ -13,7 +12,6 @@ annotation class Ann( Ann( p1 = java.lang.Byte.MAX_VALUE + 1, p2 = 1 + 1, - p3 = java.lang.Byte.MAX_VALUE - 1, p4 = 1 + 1, p5 = 1.toByte() + 1 ) class MyClass @@ -22,7 +20,6 @@ fun box(): String { val annotation = javaClass().getAnnotation(javaClass())!! if (annotation.p1 != 128) return "fail 1, expected = ${128}, actual = ${annotation.p1}" if (annotation.p2 != 2.toByte()) return "fail 2, expected = ${2}, actual = ${annotation.p2}" - if (annotation.p3 != 126.toByte()) return "fail 3, expected = ${126}, actual = ${annotation.p3}" if (annotation.p4 != 2) return "fail 4, expected = ${2}, actual = ${annotation.p4}" if (annotation.p5 != 2) return "fail 5, expected = ${2}, actual = ${annotation.p5}" return "OK" diff --git a/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueInt.kt b/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueInt.kt index 524b3729dc7..8317171ba77 100644 --- a/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueInt.kt +++ b/compiler/testData/codegen/boxWithStdlib/evaluate/maxValueInt.kt @@ -5,7 +5,6 @@ Retention(RetentionPolicy.RUNTIME) annotation class Ann( val p1: Int, val p2: Int, - val p3: Long, val p4: Long, val p5: Int ) @@ -13,7 +12,6 @@ annotation class Ann( Ann( p1 = java.lang.Integer.MAX_VALUE + 1, p2 = 1 + 1, - p3 = java.lang.Integer.MAX_VALUE + 1, p4 = 1 + 1, p5 = 1.toInt() + 1.toInt() ) class MyClass @@ -22,7 +20,6 @@ fun box(): String { val annotation = javaClass().getAnnotation(javaClass())!! if (annotation.p1 != -2147483648) return "fail 1, expected = ${-2147483648}, actual = ${annotation.p1}" if (annotation.p2 != 2) return "fail 2, expected = ${2}, actual = ${annotation.p2}" - if (annotation.p3 != -2147483648.toLong()) return "fail 3, expected = ${-2147483648}, actual = ${annotation.p3}" if (annotation.p4 != 2.toLong()) return "fail 4, expected = ${2}, actual = ${annotation.p4}" if (annotation.p5 != 2) return "fail 5, expected = ${2}, actual = ${annotation.p5}" return "OK" diff --git a/compiler/testData/diagnostics/tests/evaluate/numberBinaryOperationsInfixCall.kt b/compiler/testData/diagnostics/tests/evaluate/numberBinaryOperationsInfixCall.kt new file mode 100644 index 00000000000..77aedf5c7cc --- /dev/null +++ b/compiler/testData/diagnostics/tests/evaluate/numberBinaryOperationsInfixCall.kt @@ -0,0 +1,26 @@ +fun fooInt(p: Int) = p +fun fooLong(p: Long) = p +fun fooByte(p: Byte) = p +fun fooShort(p: Short) = p + +fun test() { + fooInt(1 plus 1) + fooByte(1 plus 1) + fooLong(1 plus 1) + fooShort(1 plus 1) + + fooInt(1 times 1) + fooByte(1 times 1) + fooLong(1 times 1) + fooShort(1 times 1) + + fooInt(1 div 1) + fooByte(1 div 1) + fooLong(1 div 1) + fooShort(1 div 1) + + fooInt(1 mod 1) + fooByte(1 mod 1) + fooLong(1 mod 1) + fooShort(1 mod 1) +} \ No newline at end of file diff --git a/compiler/testData/evaluate/isPure/enum.kt b/compiler/testData/evaluate/isPure/enum.kt index e2a521590ab..2fdd9473385 100644 --- a/compiler/testData/evaluate/isPure/enum.kt +++ b/compiler/testData/evaluate/isPure/enum.kt @@ -2,7 +2,7 @@ package test enum class MyEnum { A } -// val prop1: true +// val prop1: null val prop1 = MyEnum.A // val prop2: null diff --git a/compiler/testData/evaluate/isPure/namedConstants.kt b/compiler/testData/evaluate/isPure/namedConstants.kt new file mode 100644 index 00000000000..5b9f8987268 --- /dev/null +++ b/compiler/testData/evaluate/isPure/namedConstants.kt @@ -0,0 +1,9 @@ +package test + +val NAMED_CONSTANT = 1 + +// val prop1: null +val prop1 = NAMED_CONSTANT + +// val prop2: null +val prop2 = NAMED_CONSTANT + 1 \ No newline at end of file diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/long.kt b/compiler/testData/resolveAnnotations/parameters/expressions/long.kt index 461805b65dc..3b9392508e4 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/long.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/long.kt @@ -8,4 +8,4 @@ annotation class Ann( Ann(1 + 1, java.lang.Long.MAX_VALUE + 1 - 1, java.lang.Long.MAX_VALUE - 1) class MyClass -// EXPECTED: Ann[l1 = IntegerValueType(2): IntegerValueType(2), l2 = IntegerValueType(9223372036854775807): IntegerValueType(9223372036854775807), l3 = IntegerValueType(9223372036854775806): IntegerValueType(9223372036854775806)] +// EXPECTED: Ann[l1 = IntegerValueType(2): IntegerValueType(2), l2 = 9223372036854775807.toLong(): jet.Long, l3 = 9223372036854775806.toLong(): jet.Long] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/maxValue.kt b/compiler/testData/resolveAnnotations/parameters/expressions/maxValue.kt index 843b0a939a7..e543fff1eb3 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/maxValue.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/maxValue.kt @@ -18,4 +18,4 @@ Ann( p6 = java.lang.Long.MAX_VALUE + 1 ) class MyClass -// EXPECTED: Ann[p1 = IntegerValueType(128): IntegerValueType(128), p2 = IntegerValueType(32768): IntegerValueType(32768), p3 = IntegerValueType(-2147483648): IntegerValueType(-2147483648), p4 = IntegerValueType(-2147483648): IntegerValueType(-2147483648), p5 = 2147483648.toLong(): jet.Long, p6 = IntegerValueType(-9223372036854775808): IntegerValueType(-9223372036854775808)] +// EXPECTED: Ann[p1 = 128.toInt(): jet.Int, p2 = 32768.toInt(): jet.Int, p3 = -2147483648.toInt(): jet.Int, p4 = -2147483648.toInt(): jet.Int, p5 = 2147483648.toLong(): jet.Long, p6 = -9223372036854775808.toLong(): jet.Long] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt index b83e1e90211..aaa4d8b3589 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueByte.kt @@ -16,4 +16,4 @@ Ann( p5 = 1.toByte() + 1.toByte() ) class MyClass -// EXPECTED: Ann[p1 = IntegerValueType(128): IntegerValueType(128), p2 = IntegerValueType(2): IntegerValueType(2), p3 = IntegerValueType(128): IntegerValueType(128), p4 = 2.toInt(): jet.Int, p5 = 2.toInt(): jet.Int] +// EXPECTED: Ann[p1 = 128.toInt(): jet.Int, p2 = IntegerValueType(2): IntegerValueType(2), p3 = 128.toInt(): jet.Int, p4 = 2.toInt(): jet.Int, p5 = 2.toInt(): jet.Int] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt index 7c26a999bec..d931465286b 100644 --- a/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt +++ b/compiler/testData/resolveAnnotations/parameters/expressions/maxValueInt.kt @@ -16,4 +16,4 @@ Ann( p5 = 1.toInt() + 1.toInt() ) class MyClass -// EXPECTED: Ann[p1 = IntegerValueType(-2147483648): IntegerValueType(-2147483648), p2 = IntegerValueType(2): IntegerValueType(2), p3 = IntegerValueType(-2147483648): IntegerValueType(-2147483648), p4 = 2.toInt(): jet.Int, p5 = 2.toInt(): jet.Int] +// EXPECTED: Ann[p1 = -2147483648.toInt(): jet.Int, p2 = IntegerValueType(2): IntegerValueType(2), p3 = -2147483648.toInt(): jet.Int, p4 = 2.toInt(): jet.Int, p5 = 2.toInt(): jet.Int] diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 0f9f6d9a44c..f3c61b45489 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -2779,6 +2779,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/evaluate/numberBinaryOperationsCall.kt"); } + @TestMetadata("numberBinaryOperationsInfixCall.kt") + public void testNumberBinaryOperationsInfixCall() throws Exception { + doTest("compiler/testData/diagnostics/tests/evaluate/numberBinaryOperationsInfixCall.kt"); + } + @TestMetadata("otherOverflow.kt") public void testOtherOverflow() throws Exception { doTest("compiler/testData/diagnostics/tests/evaluate/otherOverflow.kt"); diff --git a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java index d07f3f92b07..ff5097b0108 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java @@ -106,6 +106,11 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT doIsPureTest("compiler/testData/evaluate/isPure/innerToType.kt"); } + @TestMetadata("namedConstants.kt") + public void testNamedConstants() throws Exception { + doIsPureTest("compiler/testData/evaluate/isPure/namedConstants.kt"); + } + @TestMetadata("strings.kt") public void testStrings() throws Exception { doIsPureTest("compiler/testData/evaluate/isPure/strings.kt");