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 16ce3e0e05a..908154aceed 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 @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.expressions.OperatorConventions +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.util.OperatorNameConventions import java.math.BigInteger import java.util.* @@ -340,8 +341,26 @@ private class ConstantExpressionEvaluatorVisitor( else null } - override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS, expectedType: KotlinType?): CompileTimeConstant<*>? = - evaluate(expression.getLeft(), expectedType) + override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS, expectedType: KotlinType?): CompileTimeConstant<*>? { + val compileTimeConstant = evaluate(expression.left, expectedType) + if (compileTimeConstant != null) { + if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) { + val constantType = when(compileTimeConstant) { + is TypedCompileTimeConstant<*> -> + compileTimeConstant.type + is IntegerValueTypeConstant -> + compileTimeConstant.getType(expectedType) + else -> + throw IllegalStateException("Unexpected compileTimeConstant class: ${compileTimeConstant.javaClass.canonicalName}") + + } + if (!constantType.isSubtypeOf(expectedType)) return null + + } + } + + return compileTimeConstant + } override fun visitBinaryExpression(expression: KtBinaryExpression, expectedType: KotlinType?): CompileTimeConstant<*>? { val leftExpression = expression.getLeft() ?: return null diff --git a/compiler/testData/diagnostics/tests/modifiers/const/applicability.kt b/compiler/testData/diagnostics/tests/modifiers/const/applicability.kt index 0999b2c3548..5e1887e208e 100644 --- a/compiler/testData/diagnostics/tests/modifiers/const/applicability.kt +++ b/compiler/testData/diagnostics/tests/modifiers/const/applicability.kt @@ -1,4 +1,4 @@ -// !DIAGNOSTICS:-UNUSED_VARIABLE +// !DIAGNOSTICS:-UNUSED_VARIABLE,-CAST_NEVER_SUCCEEDS import kotlin.reflect.KProperty @@ -67,7 +67,11 @@ class Outer { const val defaultGetter = 19 get -const val nonConstInitializer = foo() +const val nonConstInitializer1 = foo() +const val nonConstInitializer2 = 1 as String +const val nonConstInitializer3 = 1.0 as String +const val nonConstInitializer4 = 1 as Double +const val nonConstInitializer5 = "2" as Int // ------------------ class Delegate { diff --git a/compiler/testData/diagnostics/tests/modifiers/const/applicability.txt b/compiler/testData/diagnostics/tests/modifiers/const/applicability.txt index e25c07ffe6d..90ac0441f60 100644 --- a/compiler/testData/diagnostics/tests/modifiers/const/applicability.txt +++ b/compiler/testData/diagnostics/tests/modifiers/const/applicability.txt @@ -2,7 +2,11 @@ package public const val defaultGetter: kotlin.Int = 19 public const val delegated: kotlin.Int -public const val nonConstInitializer: kotlin.Int +public const val nonConstInitializer1: kotlin.Int +public const val nonConstInitializer2: kotlin.String +public const val nonConstInitializer3: kotlin.String +public const val nonConstInitializer4: kotlin.Double +public const val nonConstInitializer5: kotlin.Int private val privateTopLevel: kotlin.Int = 3 public const var topLeveLVar: kotlin.Int public const val topLevel: kotlin.Int = 0