From 36810c5bbb5553886f3ddd21d20c3d3cfcac1a5e Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Fri, 24 Jan 2014 14:01:48 +0400 Subject: [PATCH] Move IS_PURE for constant inside CompileTimeConstant --- .../evaluate/ConstantExpressionEvaluator.kt | 102 ++++++++---------- .../jet/lang/resolve/BindingContext.java | 1 - .../resolve/calls/CallExpressionResolver.java | 4 +- .../constants/CompileTimeConstantChecker.java | 7 +- compiler/testData/evaluate/isPure/enum.kt | 4 +- .../testData/evaluate/isPure/innerToType.kt | 8 +- .../evaluate/isPure/namedConstants.kt | 4 +- compiler/testData/evaluate/isPure/strings.kt | 10 +- compiler/testData/evaluate/isPure/toType.kt | 14 +-- .../isPure/unaryMinusIndepWoExpType.kt | 8 +- .../isPure/unaryMinusIndependentExpType.kt | 32 +++--- .../AbstractEvaluateExpressionTest.kt | 4 +- .../JavaAnnotationArgumentResolver.java | 16 +-- .../resolve/constants/AnnotationValue.java | 2 +- .../lang/resolve/constants/ArrayValue.java | 2 +- .../lang/resolve/constants/BooleanValue.java | 2 +- .../jet/lang/resolve/constants/ByteValue.java | 4 +- .../jet/lang/resolve/constants/CharValue.java | 4 +- .../constants/CompileTimeConstant.java | 9 +- .../lang/resolve/constants/DoubleValue.java | 2 +- .../jet/lang/resolve/constants/EnumValue.java | 2 +- .../lang/resolve/constants/ErrorValue.java | 2 +- .../lang/resolve/constants/FloatValue.java | 2 +- .../jet/lang/resolve/constants/IntValue.java | 4 +- .../constants/IntegerValueTypeConstant.java | 2 +- .../resolve/constants/JavaClassValue.java | 2 +- .../jet/lang/resolve/constants/LongValue.java | 4 +- .../jet/lang/resolve/constants/NullValue.java | 2 +- .../lang/resolve/constants/ShortValue.java | 4 +- .../lang/resolve/constants/StringValue.java | 3 +- 30 files changed, 127 insertions(+), 139 deletions(-) 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 cc78c37d146..c6882c2baf7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -94,18 +94,13 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet fun isLongWithSuffix() = expression.getNode().getElementType() == JetNodeTypes.INTEGER_CONSTANT && hasLongSuffix(text) - return createCompileTimeConstant(result, expression, expectedType, !isLongWithSuffix()) + return createCompileTimeConstant(result, expectedType, !isLongWithSuffix()) } override fun visitParenthesizedExpression(expression: JetParenthesizedExpression, expectedType: JetType?): CompileTimeConstant<*>? { val deparenthesizedExpression = JetPsiUtil.deparenthesize(expression) if (deparenthesizedExpression != null && deparenthesizedExpression != expression) { - val compileTimeConstant = evaluate(deparenthesizedExpression, expectedType) - val isDeparentesizedPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, deparenthesizedExpression) - if (isDeparentesizedPure != null && isDeparentesizedPure!!) { - trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true) - } - return compileTimeConstant + return evaluate(deparenthesizedExpression, expectedType) } return null } @@ -135,7 +130,10 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet sb.append(constant.getValue()) } } - return if (!interupted) createCompileTimeConstant(sb.toString(), expression, expectedType, true, canBeUsedInAnnotation) else null + return if (!interupted) + createCompileTimeConstant(sb.toString(), expectedType, + isPure = true, canBeUsedInAnnotation = canBeUsedInAnnotation) + else null } override fun visitBinaryExpression(expression: JetBinaryExpression, expectedType: JetType?): CompileTimeConstant<*>? { @@ -163,7 +161,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet JetTokens.OROR -> leftValue as Boolean || rightValue as Boolean else -> throw IllegalArgumentException("Unknown boolean operation token ${operationToken}") } - return createCompileTimeConstant(result, expression, expectedType) + return createCompileTimeConstant(result, expectedType) } else { return evaluateCall(expression, expression.getOperationReference(), leftExpression, expectedType) @@ -183,10 +181,10 @@ 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) ?: false + val isArgumentPure = isPureConstant(argumentForReceiver.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS - return createCompileTimeConstant(result, fullExpression, expectedType, !isNumberConversionMethod && isArgumentPure, canBeUsedInAnnotation) + return createCompileTimeConstant(result, expectedType, !isNumberConversionMethod && isArgumentPure, canBeUsedInAnnotation) } else if (argumentsEntrySet.size() == 1) { val (parameter, argument) = argumentsEntrySet.first() @@ -200,16 +198,14 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val result = evaluateBinaryAndCheck(argumentForReceiver, argumentForParameter, resultingDescriptorName.asString(), callExpression) + val areArgumentsPure = isPureConstant(argumentForReceiver.expression) && isPureConstant(argumentForParameter.expression) val canBeUsedInAnnotation = canBeUsedInAnnotation(argumentForReceiver.expression) && canBeUsedInAnnotation(argumentForParameter.expression) - val context = EvaluatorContext(canBeUsedInAnnotation) + val c = EvaluatorContext(canBeUsedInAnnotation, areArgumentsPure) return when(resultingDescriptorName) { - OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, context) - OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, context) + OperatorConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression, c) + OperatorConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression, c) else -> { - val areArgumentsPure = trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForReceiver.expression) ?: false && - trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, argumentForParameter.expression) ?: false - - createCompileTimeConstant(result, fullExpression, expectedType, areArgumentsPure, canBeUsedInAnnotation) + createCompileTimeConstant(result, expectedType, areArgumentsPure, canBeUsedInAnnotation) } } } @@ -218,6 +214,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet } private fun canBeUsedInAnnotation(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.canBeUsedInAnnotations() ?: false + private fun isPureConstant(expression: JetExpression) = trace.get(BindingContext.COMPILE_TIME_VALUE, expression)?.isPure() ?: false private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: JetExpression): Any? { val functions = unaryOperations[UnaryOperationKey(receiver.ctcType, name)] @@ -299,8 +296,8 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet compileTimeConstant.getValue(expectedType ?: TypeUtils.NO_EXPECTED_TYPE) else compileTimeConstant.getValue() - return createCompileTimeConstant(value, expression, expectedType, false, - AnnotationUtils.isPropertyCompileTimeConstant(callableDescriptor)) + return createCompileTimeConstant(value, expectedType, isPure = false, + canBeUsedInAnnotation = AnnotationUtils.isPropertyCompileTimeConstant(callableDescriptor)) } } return null @@ -321,11 +318,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet // MyEnum.A, Integer.MAX_VALUE if (selectorExpression != null) { - val compileTimeConstant = evaluate(selectorExpression, expectedType) - if (trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, selectorExpression) == true) { - trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true) - } - return compileTimeConstant + return evaluate(selectorExpression, expectedType) } return null @@ -423,16 +416,9 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet return OperationArgument(evaluationResult, compileTimeType, expression) } - fun createCompileTimeConstant(value: Any?, expression: JetExpression, expectedType: JetType?, isPure: Boolean = true, canBeUsedInAnnotation: Boolean = true): CompileTimeConstant<*>? { - val c = EvaluatorContext(canBeUsedInAnnotation) - val compileTimeConstant = - if (isPure) { - trace.record(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression, true) - createCompileTimeConstant(value, c, expectedType ?: TypeUtils.NO_EXPECTED_TYPE) - } - else createCompileTimeConstant(value, c) - - return compileTimeConstant + fun createCompileTimeConstant(value: Any?, expectedType: JetType?, isPure: Boolean = true, canBeUsedInAnnotation: Boolean = true): CompileTimeConstant<*>? { + val c = EvaluatorContext(canBeUsedInAnnotation, isPure) + return createCompileTimeConstant(value, c, if (isPure) expectedType ?: TypeUtils.NO_EXPECTED_TYPE else null) } } @@ -453,7 +439,7 @@ public fun recordCompileTimeValueForInitializerIfNeeded( } public fun IntegerValueTypeConstant.createCompileTimeConstantWithType(expectedType: JetType): CompileTimeConstant<*>? - = createCompileTimeConstant(getValue(expectedType), EvaluatorContext(canBeUsedInAnnotations())) + = createCompileTimeConstant(this.getValue(expectedType), EvaluatorContext(this.canBeUsedInAnnotations(), this.isPure())) private fun hasLongSuffix(text: String) = text.endsWith('l') || text.endsWith('L') @@ -510,16 +496,16 @@ private fun parseBoolean(text: String): Boolean { } -private fun createCompileTimeConstantForEquals(result: Any?, operationReference: JetExpression, context: EvaluatorContext): CompileTimeConstant<*>? { +private fun createCompileTimeConstantForEquals(result: Any?, operationReference: JetExpression, c: EvaluatorContext): CompileTimeConstant<*>? { if (result is Boolean) { assert(operationReference is JetSimpleNameExpression, "This method should be called only for equals operations") val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() return when (operationToken) { - JetTokens.EQEQ -> BooleanValue(result, context.canBeUsedInAnnotation) - JetTokens.EXCLEQ -> BooleanValue(!result, context.canBeUsedInAnnotation) + JetTokens.EQEQ -> BooleanValue(result, c.canBeUsedInAnnotation) + JetTokens.EXCLEQ -> BooleanValue(!result, c.canBeUsedInAnnotation) JetTokens.IDENTIFIER -> { assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.EQUALS, "This method should be called only for equals operations") - return BooleanValue(result, context.canBeUsedInAnnotation) + return BooleanValue(result, c.canBeUsedInAnnotation) } else -> throw IllegalStateException("Unknown equals operation token: $operationToken ${operationReference.getText()}") } @@ -527,18 +513,18 @@ private fun createCompileTimeConstantForEquals(result: Any?, operationReference: return null } -private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: JetExpression, context: EvaluatorContext): CompileTimeConstant<*>? { +private fun createCompileTimeConstantForCompareTo(result: Any?, operationReference: JetExpression, c: EvaluatorContext): CompileTimeConstant<*>? { if (result is Int) { assert(operationReference is JetSimpleNameExpression, "This method should be called only for compareTo operations") val operationToken = (operationReference as JetSimpleNameExpression).getReferencedNameElementType() return when (operationToken) { - JetTokens.LT -> BooleanValue(result < 0, context.canBeUsedInAnnotation) - JetTokens.LTEQ -> BooleanValue(result <= 0, context.canBeUsedInAnnotation) - JetTokens.GT -> BooleanValue(result > 0, context.canBeUsedInAnnotation) - JetTokens.GTEQ -> BooleanValue(result >= 0, context.canBeUsedInAnnotation) + JetTokens.LT -> BooleanValue(result < 0, c.canBeUsedInAnnotation) + JetTokens.LTEQ -> BooleanValue(result <= 0, c.canBeUsedInAnnotation) + JetTokens.GT -> BooleanValue(result > 0, c.canBeUsedInAnnotation) + JetTokens.GTEQ -> BooleanValue(result >= 0, c.canBeUsedInAnnotation) JetTokens.IDENTIFIER -> { assert ((operationReference as JetSimpleNameExpression).getReferencedNameAsName() == OperatorConventions.COMPARE_TO, "This method should be called only for compareTo operations") - return IntValue(result, context.canBeUsedInAnnotation) + return IntValue(result, c.canBeUsedInAnnotation, c.isPure) } else -> throw IllegalStateException("Unknown compareTo operation token: $operationToken") } @@ -562,15 +548,15 @@ private fun createStringConstant(value: CompileTimeConstant<*>?): StringValue? { private fun createCompileTimeConstant(value: Any?, c: EvaluatorContext, expectedType: JetType? = null): CompileTimeConstant<*>? { if (expectedType == null) { when(value) { - is Byte -> return ByteValue(value, c.canBeUsedInAnnotation) - is Short -> return ShortValue(value, c.canBeUsedInAnnotation) - is Int -> return IntValue(value, c.canBeUsedInAnnotation) - is Long -> return LongValue(value, c.canBeUsedInAnnotation) + is Byte -> return ByteValue(value, c.canBeUsedInAnnotation, c.isPure) + is Short -> return ShortValue(value, c.canBeUsedInAnnotation, c.isPure) + is Int -> return IntValue(value, c.canBeUsedInAnnotation, c.isPure) + is Long -> return LongValue(value, c.canBeUsedInAnnotation, c.isPure) } } return when(value) { is Byte, is Short, is Int, is Long -> getIntegerValue((value as Number).toLong(), c, expectedType) - is Char -> CharValue(value, c.canBeUsedInAnnotation) + is Char -> CharValue(value, c.canBeUsedInAnnotation, c.isPure) is Float -> FloatValue(value, c.canBeUsedInAnnotation) is Double -> DoubleValue(value, c.canBeUsedInAnnotation) is Boolean -> BooleanValue(value, c.canBeUsedInAnnotation) @@ -584,8 +570,8 @@ fun isIntegerType(value: Any?) = value is Byte || value is Short || value is Int private fun getIntegerValue(value: Long, c: EvaluatorContext, expectedType: JetType): CompileTimeConstant<*>? { fun defaultIntegerValue(value: Long) = when (value) { - value.toInt().toLong() -> IntValue(value.toInt(), c.canBeUsedInAnnotation) - else -> LongValue(value, c.canBeUsedInAnnotation) + value.toInt().toLong() -> IntValue(value.toInt(), c.canBeUsedInAnnotation, c.isPure) + else -> LongValue(value, c.canBeUsedInAnnotation, c.isPure) } if (CompileTimeConstantChecker.noExpectedTypeOrError(expectedType)) { @@ -595,16 +581,16 @@ private fun getIntegerValue(value: Long, c: EvaluatorContext, expectedType: JetT val builtIns = KotlinBuiltIns.getInstance() return when (TypeUtils.makeNotNullable(expectedType)) { - builtIns.getLongType() -> LongValue(value, c.canBeUsedInAnnotation) + builtIns.getLongType() -> LongValue(value, c.canBeUsedInAnnotation, c.isPure) builtIns.getShortType() -> when (value) { - value.toShort().toLong() -> ShortValue(value.toShort(), c.canBeUsedInAnnotation) + value.toShort().toLong() -> ShortValue(value.toShort(), c.canBeUsedInAnnotation, c.isPure) else -> defaultIntegerValue(value) } builtIns.getByteType() -> when (value) { - value.toByte().toLong() -> ByteValue(value.toByte(), c.canBeUsedInAnnotation) + value.toByte().toLong() -> ByteValue(value.toByte(), c.canBeUsedInAnnotation, c.isPure) else -> defaultIntegerValue(value) } - builtIns.getCharType() -> IntValue(value.toInt(), c.canBeUsedInAnnotation) + builtIns.getCharType() -> IntValue(value.toInt(), c.canBeUsedInAnnotation, c.isPure) else -> defaultIntegerValue(value) } } @@ -636,7 +622,7 @@ private fun getCompileTimeType(c: JetType): CompileTimeType? { } } -private class EvaluatorContext(val canBeUsedInAnnotation: Boolean) +private class EvaluatorContext(val canBeUsedInAnnotation: Boolean, val isPure: Boolean) private class CompileTimeType diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 1200e3ec16f..d6c1be917f5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -75,7 +75,6 @@ public interface BindingContext { WritableSlice ANNOTATION = Slices.sliceBuilder().setOpposite(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT).build(); - WritableSlice IS_PURE_CONSTANT_EXPRESSION = Slices.createSimpleSlice(); WritableSlice> COMPILE_TIME_VALUE = Slices.createSimpleSlice(); WritableSlice> COMPILE_TIME_INITIALIZER = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java index f18cf0ec1ef..3936e468eb3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallExpressionResolver.java @@ -466,11 +466,9 @@ public class CallExpressionResolver { } CompileTimeConstant value = ConstantExpressionEvaluator.object$.evaluate(expression, context.trace, context.expectedType); - if (Boolean.TRUE.equals(context.trace.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, expression))) { - if (value != null) { + if (value != null && value.isPure()) { return BasicExpressionTypingVisitor.createCompileTimeConstantTypeInfo(value, expression, context); } - } JetTypeInfo typeInfo = JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo()); if (context.contextDependency == INDEPENDENT) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java index 9bd7d1a0ad2..5c7fe861781 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java @@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages; import org.jetbrains.jet.lang.psi.JetConstantExpression; import org.jetbrains.jet.lang.psi.JetElement; -import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; @@ -167,7 +166,7 @@ public class CompileTimeConstantChecker { if (text.charAt(0) != '\\') { // No escape if (text.length() == 1) { - return new CharValue(text.charAt(0), true); + return new CharValue(text.charAt(0), true, true); } return createErrorValue(TOO_MANY_CHARACTERS_IN_CHARACTER_LITERAL.on(expression, expression)); } @@ -190,13 +189,13 @@ public class CompileTimeConstantChecker { if (escaped == null) { return illegalEscape(expression); } - return new CharValue(escaped, true); + return new CharValue(escaped, true, true); case 5: // unicode escape if (escape.charAt(0) == 'u') { try { Integer intValue = Integer.valueOf(escape.substring(1), 16); - return new CharValue((char) intValue.intValue(), true); + return new CharValue((char) intValue.intValue(), true, true); } catch (NumberFormatException e) { // Will be reported below } diff --git a/compiler/testData/evaluate/isPure/enum.kt b/compiler/testData/evaluate/isPure/enum.kt index 2fdd9473385..2bacc61efed 100644 --- a/compiler/testData/evaluate/isPure/enum.kt +++ b/compiler/testData/evaluate/isPure/enum.kt @@ -2,8 +2,8 @@ package test enum class MyEnum { A } -// val prop1: null +// val prop1: false val prop1 = MyEnum.A -// val prop2: null +// val prop2: false val prop2 = javaClass() diff --git a/compiler/testData/evaluate/isPure/innerToType.kt b/compiler/testData/evaluate/isPure/innerToType.kt index 0416a92cae2..4eda6cca3e5 100644 --- a/compiler/testData/evaluate/isPure/innerToType.kt +++ b/compiler/testData/evaluate/isPure/innerToType.kt @@ -1,13 +1,13 @@ package test -// val prop1: null +// val prop1: false val prop1 = 1.toLong() + 1 -// val prop2: null +// val prop2: false val prop2 = -1.toInt() -// val prop3: null +// val prop3: false val prop3 = 1 + 1.toByte() -// val prop4: null +// val prop4: false val prop4 = 1 + 1.toShort() + 1 \ No newline at end of file diff --git a/compiler/testData/evaluate/isPure/namedConstants.kt b/compiler/testData/evaluate/isPure/namedConstants.kt index 5b9f8987268..3a1628a85ec 100644 --- a/compiler/testData/evaluate/isPure/namedConstants.kt +++ b/compiler/testData/evaluate/isPure/namedConstants.kt @@ -2,8 +2,8 @@ package test val NAMED_CONSTANT = 1 -// val prop1: null +// val prop1: false val prop1 = NAMED_CONSTANT -// val prop2: null +// val prop2: false val prop2 = NAMED_CONSTANT + 1 \ No newline at end of file diff --git a/compiler/testData/evaluate/isPure/strings.kt b/compiler/testData/evaluate/isPure/strings.kt index 16d3937173c..779c4986182 100644 --- a/compiler/testData/evaluate/isPure/strings.kt +++ b/compiler/testData/evaluate/isPure/strings.kt @@ -1,16 +1,16 @@ package test -// val prop1: true +// val prop1: false val prop1 = "" -// val prop2: true +// val prop2: false val prop2 = "a" -// val prop3: true +// val prop3: false val prop3 = "\"a\"" -// val prop5: true +// val prop5: false val prop5 = "a${1 + 1}" -// val prop6: true +// val prop6: false val prop6 = "a" + "b" diff --git a/compiler/testData/evaluate/isPure/toType.kt b/compiler/testData/evaluate/isPure/toType.kt index 646696ddd4d..8ec5e7eeb68 100644 --- a/compiler/testData/evaluate/isPure/toType.kt +++ b/compiler/testData/evaluate/isPure/toType.kt @@ -1,22 +1,22 @@ package test -// val prop1: null +// val prop1: false val prop1 = 1.toLong() -// val prop2: null +// val prop2: false val prop2 = 1.toInt() -// val prop3: null +// val prop3: false val prop3 = 1.toByte() -// val prop4: null +// val prop4: false val prop4 = 1.toShort() -// val prop5: null +// val prop5: false val prop5 = 1.toChar() -// val prop6: null +// val prop6: false val prop6 = 1.toDouble() -// val prop7: null +// val prop7: false val prop7 = 1.toFloat() \ No newline at end of file diff --git a/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt b/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt index 3b868c2c76f..77398062a1c 100644 --- a/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt +++ b/compiler/testData/evaluate/isPure/unaryMinusIndepWoExpType.kt @@ -3,14 +3,14 @@ package test // val p1: true val p1 = -1 -// val p2: null +// val p2: false val p2 = -1.toLong() -// val p3: null +// val p3: false val p3 = -1.toByte() -// val p4: null +// val p4: false val p4 = -1.toInt() -// val p5: null +// val p5: false val p5 = -1.toShort() diff --git a/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt b/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt index 821c67f9fcf..747bca1b79f 100644 --- a/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt +++ b/compiler/testData/evaluate/isPure/unaryMinusIndependentExpType.kt @@ -12,52 +12,52 @@ val p3: Byte = -1 // val p4: true val p4: Short = -1 -// val l1: null +// val l1: false val l1: Long = -1.toLong() -// val l2: null +// val l2: false val l2: Byte = -1.toLong() -// val l3: null +// val l3: false val l3: Int = -1.toLong() -// val l4: null +// val l4: false val l4: Short = -1.toLong() -// val b1: null +// val b1: false val b1: Byte = -1.toByte() -// val b2: null +// val b2: false val b2: Int = -1.toByte() -// val b3: null +// val b3: false val b3: Long = -1.toByte() -// val b4: null +// val b4: false val b4: Short = -1.toByte() -// val i1: null +// val i1: false val i1: Byte = -1.toInt() -// val i2: null +// val i2: false val i2: Int = -1.toInt() -// val i3: null +// val i3: false val i3: Long = -1.toInt() -// val i4: null +// val i4: false val i4: Short = -1.toInt() -// val s1: null +// val s1: false val s1: Byte = -1.toShort() -// val s2: null +// val s2: false val s2: Int = -1.toShort() -// val s3: null +// val s3: false val s3: Long = -1.toShort() -// val s4: null +// val s4: false val s4: Short = -1.toShort() \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt index 574a2dbb72f..0004d9f0a80 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt +++ b/compiler/tests/org/jetbrains/jet/evaluate/AbstractEvaluateExpressionTest.kt @@ -54,8 +54,8 @@ abstract class AbstractEvaluateExpressionTest: AbstractAnnotationDescriptorResol fun doIsPureTest(path: String) { doTest(path) { property, context -> - val isPureKey = context.get(BindingContext.IS_PURE_CONSTANT_EXPRESSION, property.getInitializer()) - isPureKey.toString() + val compileTimeConstant = context.get(BindingContext.COMPILE_TIME_VALUE, property.getInitializer()) + compileTimeConstant?.isPure().toString() } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java index dca3b8e750d..f27c6178ece 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java @@ -172,30 +172,30 @@ public final class JavaAnnotationArgumentResolver { return new StringValue((String) value, canBeUseInAnnotation); } else if (value instanceof Byte) { - return new ByteValue((Byte) value, canBeUseInAnnotation); + return new ByteValue((Byte) value, canBeUseInAnnotation, false); } else if (value instanceof Short) { - return new ShortValue((Short) value, canBeUseInAnnotation); + return new ShortValue((Short) value, canBeUseInAnnotation, false); } else if (value instanceof Character) { - return new CharValue((Character) value, canBeUseInAnnotation); + return new CharValue((Character) value, canBeUseInAnnotation, false); } else if (value instanceof Integer) { KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); Integer integer = (Integer) value; if (builtIns.getShortType().equals(expectedType)) { - return new ShortValue(integer.shortValue(), canBeUseInAnnotation); + return new ShortValue(integer.shortValue(), canBeUseInAnnotation, false); } else if (builtIns.getByteType().equals(expectedType)) { - return new ByteValue(integer.byteValue(), canBeUseInAnnotation); + return new ByteValue(integer.byteValue(), canBeUseInAnnotation, false); } else if (builtIns.getCharType().equals(expectedType)) { - return new CharValue((char) integer.intValue(), canBeUseInAnnotation); + return new CharValue((char) integer.intValue(), canBeUseInAnnotation, false); } - return new IntValue(integer, canBeUseInAnnotation); + return new IntValue(integer, canBeUseInAnnotation, false); } else if (value instanceof Long) { - return new LongValue((Long) value, canBeUseInAnnotation); + return new LongValue((Long) value, canBeUseInAnnotation, false); } else if (value instanceof Float) { return new FloatValue((Float) value, canBeUseInAnnotation); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java index 3eed4039b4f..2a384a4e6e7 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/AnnotationValue.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class AnnotationValue extends CompileTimeConstant { public AnnotationValue(@NotNull AnnotationDescriptor value) { - super(value, true); + super(value, true, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java index d082d2a7410..067a3bef32b 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ArrayValue.java @@ -28,7 +28,7 @@ public class ArrayValue extends CompileTimeConstant> private final JetType type; public ArrayValue(@NotNull List> value, @NotNull JetType type, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + super(value, canBeUsedInAnnotations, false); this.type = type; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java index 76494dbc3ea..53a169588d3 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/BooleanValue.java @@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.JetType; public class BooleanValue extends CompileTimeConstant { public BooleanValue(boolean value, boolean canBeUseInAnnotation) { - super(value, canBeUseInAnnotation); + super(value, canBeUseInAnnotation, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java index a8e53b60332..a6e9142c11e 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ByteValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class ByteValue extends CompileTimeConstant { - public ByteValue(byte value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public ByteValue(byte value, boolean canBeUsedInAnnotations, boolean pure) { + super(value, canBeUsedInAnnotations, pure); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java index f4ff6ac4e2c..5c3c74f09ec 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CharValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class CharValue extends CompileTimeConstant { - public CharValue(char value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public CharValue(char value, boolean canBeUsedInAnnotations, boolean pure) { + super(value, canBeUsedInAnnotations, pure); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java index 07dce8a09bf..cd8da52c273 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstant.java @@ -25,16 +25,23 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public abstract class CompileTimeConstant { protected final T value; private final boolean canBeUsedInAnnotations; + // if false = constant type cannot be changed, ex. val a: Long = 1.toInt() (should be a TYPE_MISMATCH error, 1.toInt() isn't pure) + private final boolean isPure; - protected CompileTimeConstant(T value, boolean canBeUsedInAnnotations) { + protected CompileTimeConstant(T value, boolean canBeUsedInAnnotations, boolean pure) { this.value = value; this.canBeUsedInAnnotations = canBeUsedInAnnotations; + this.isPure = pure; } public boolean canBeUsedInAnnotations() { return canBeUsedInAnnotations; } + public boolean isPure() { + return isPure; + } + @Nullable public T getValue() { return value; diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java index 6f06ee2e642..54deb33ba02 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/DoubleValue.java @@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.JetType; public class DoubleValue extends CompileTimeConstant { public DoubleValue(double value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + super(value, canBeUsedInAnnotations, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java index 3df8a943569..43a627325f1 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/EnumValue.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class EnumValue extends CompileTimeConstant { public EnumValue(@NotNull ClassDescriptor value) { - super(value, true); + super(value, true, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java index 465dde4892c..ffe6f103d57 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ErrorValue.java @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public abstract class ErrorValue extends CompileTimeConstant { public ErrorValue() { - super(null, true); + super(null, true, false); } @Override diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java index 3e439e467a7..b0bbcf459f2 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/FloatValue.java @@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.JetType; public class FloatValue extends CompileTimeConstant { public FloatValue(float value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + super(value, canBeUsedInAnnotations, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java index 5aef72b9579..885cc7bda92 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class IntValue extends CompileTimeConstant { - public IntValue(int value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public IntValue(int value, boolean canBeUsedInAnnotations, boolean pure) { + super(value, canBeUsedInAnnotations, pure); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java index edff08673ea..4f1d5de1275 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/IntegerValueTypeConstant.java @@ -31,7 +31,7 @@ public class IntegerValueTypeConstant extends CompileTimeConstant { private final IntegerValueTypeConstructor typeConstructor; public IntegerValueTypeConstant(@NotNull Number value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + super(value, canBeUsedInAnnotations, true); this.typeConstructor = new IntegerValueTypeConstructor(value.longValue()); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java index 60b2e3f631b..b0c4dd3eafc 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/JavaClassValue.java @@ -24,7 +24,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class JavaClassValue extends CompileTimeConstant { public JavaClassValue(@NotNull JetType value) { - super(value, true); + super(value, true, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java index 7c4fcb51c17..4dc8fdcaf1c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/LongValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class LongValue extends CompileTimeConstant { - public LongValue(long value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public LongValue(long value, boolean canBeUsedInAnnotations, boolean pure) { + super(value, canBeUsedInAnnotations, pure); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java index e9cdaeb553f..7b79f77f895 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/NullValue.java @@ -26,7 +26,7 @@ public class NullValue extends CompileTimeConstant { public static final NullValue NULL = new NullValue(); private NullValue() { - super(null, false); + super(null, false, false); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java index cf8f69d60dc..fee473bea0c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/ShortValue.java @@ -23,8 +23,8 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; public class ShortValue extends CompileTimeConstant { - public ShortValue(short value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + public ShortValue(short value, boolean canBeUsedInAnnotations, boolean pure) { + super(value, canBeUsedInAnnotations, pure); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java index f46abde8d93..a90ffb1f7a9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java @@ -23,9 +23,8 @@ import org.jetbrains.jet.lang.types.JetType; public class StringValue extends CompileTimeConstant { - public StringValue(String value, boolean canBeUsedInAnnotations) { - super(value, canBeUsedInAnnotations); + super(value, canBeUsedInAnnotations, false); } @NotNull