[K2] Allow using simple boolean expressions in constant position

Such behavior is not the same as in K1, but it is more consistent.

#KT-64400 Fixed
This commit is contained in:
Ivan Kylchik
2023-12-05 16:58:44 +01:00
committed by Space Team
parent 38ea2ce973
commit f8e9e99d87
13 changed files with 129 additions and 40 deletions
@@ -23951,6 +23951,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/modifiers/const/arrayInAnnotationArgumentType.kt");
}
@Test
@TestMetadata("compare.kt")
public void testCompare() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/const/compare.kt");
}
@Test
@TestMetadata("constInteraction.kt")
public void testConstInteraction() throws Exception {
@@ -23951,6 +23951,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/modifiers/const/arrayInAnnotationArgumentType.kt");
}
@Test
@TestMetadata("compare.kt")
public void testCompare() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/const/compare.kt");
}
@Test
@TestMetadata("constInteraction.kt")
public void testConstInteraction() throws Exception {
@@ -23945,6 +23945,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/modifiers/const/arrayInAnnotationArgumentType.kt");
}
@Test
@TestMetadata("compare.kt")
public void testCompare() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/const/compare.kt");
}
@Test
@TestMetadata("constInteraction.kt")
public void testConstInteraction() throws Exception {
@@ -23951,6 +23951,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/modifiers/const/arrayInAnnotationArgumentType.kt");
}
@Test
@TestMetadata("compare.kt")
public void testCompare() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/const/compare.kt");
}
@Test
@TestMetadata("constInteraction.kt")
public void testConstInteraction() throws Exception {
@@ -96,10 +96,6 @@ internal fun checkConstantArguments(
return ConstantArgumentKind.NOT_CONST
}
if (expression.isForbiddenComplexConstant(session)) {
return ConstantArgumentKind.NOT_CONST
}
for (exp in (expression as FirCall).arguments) {
if (exp is FirResolvedQualifier || exp is FirGetClassCall || exp.getExpandedType().isUnsignedType) {
return ConstantArgumentKind.NOT_CONST
@@ -162,7 +158,7 @@ internal fun checkConstantArguments(
if (calleeReference !is FirResolvedNamedReference) return ConstantArgumentKind.NOT_CONST
val symbol = calleeReference.resolvedSymbol as? FirNamedFunctionSymbol ?: return ConstantArgumentKind.NOT_CONST
if (!symbol.canBeEvaluated() && !expression.isCompileTimeBuiltinCall(session) || expression.isForbiddenComplexConstant(session)) {
if (!symbol.canBeEvaluated() && !expression.isCompileTimeBuiltinCall(session)) {
return ConstantArgumentKind.NOT_CONST
}
@@ -214,34 +210,6 @@ internal fun checkConstantArguments(
return null
}
private fun FirExpression.isForbiddenComplexConstant(session: FirSession): Boolean {
val forbidComplexBooleanExpressions = session.languageVersionSettings.supportsFeature(
LanguageFeature.ProhibitSimplificationOfNonTrivialConstBooleanExpressions
)
val intrinsicConstEvaluation = session.languageVersionSettings.supportsFeature(
LanguageFeature.IntrinsicConstEvaluation
)
return !intrinsicConstEvaluation && forbidComplexBooleanExpressions && isComplexBooleanConstant(session)
}
private fun FirExpression.isComplexBooleanConstant(session: FirSession): Boolean {
return when {
!resolvedType.fullyExpandedType(session).isBoolean -> false
this is FirConstExpression<*> -> false
usesVariableAsConstant -> false
else -> true
}
}
/**
* See: org.jetbranis.kotlin.resolve.constants.CompileTimeConstant.Parameters.usesVariableAsConstant
*/
@Suppress("RecursivePropertyAccessor")
private val FirExpression.usesVariableAsConstant: Boolean
get() = this is FirPropertyAccessExpression && toResolvedCallableSymbol()?.isConst == true
|| this is FirQualifiedAccessExpression && explicitReceiver?.usesVariableAsConstant != false
|| this is FirCall && this.arguments.any { it.usesVariableAsConstant }
private val compileTimeFunctions = setOf(
*OperatorNameConventions.BINARY_OPERATION_NAMES.toTypedArray(), *OperatorNameConventions.UNARY_OPERATION_NAMES.toTypedArray(),
OperatorNameConventions.SHL, OperatorNameConventions.SHR, OperatorNameConventions.USHR,
@@ -0,0 +1,22 @@
const val INT = 0
const val LONG = 0L
const val compareInt1 = 1 < 2
const val compareInt2 = 1 <= 3
const val compareInt3 = 1 > 4
const val compareInt4 = 1 >= 5
const val compareInt5 = INT < 2
const val compareInt6 = INT <= 3
const val compareInt7 = INT > 4
const val compareInt8 = INT >= 5
const val compareLong1 = 1L < 2L
const val compareLong2 = 1L <= 3L
const val compareLong3 = 1L > 4L
const val compareLong4 = 1L >= 5L
const val compareLong5 = LONG < 2L
const val compareLong6 = LONG <= 3L
const val compareLong7 = LONG > 4L
const val compareLong8 = LONG >= 5L
@@ -0,0 +1,22 @@
const val INT = 0
const val LONG = 0L
const val compareInt1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1 < 2<!>
const val compareInt2 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1 <= 3<!>
const val compareInt3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1 > 4<!>
const val compareInt4 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1 >= 5<!>
const val compareInt5 = INT < 2
const val compareInt6 = INT <= 3
const val compareInt7 = INT > 4
const val compareInt8 = INT >= 5
const val compareLong1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1L < 2L<!>
const val compareLong2 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1L <= 3L<!>
const val compareLong3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1L > 4L<!>
const val compareLong4 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1L >= 5L<!>
const val compareLong5 = LONG < 2L
const val compareLong6 = LONG <= 3L
const val compareLong7 = LONG > 4L
const val compareLong8 = LONG >= 5L
@@ -0,0 +1,46 @@
// !LANGUAGE: -IntrinsicConstEvaluation
const val equalsBoolean1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>true.equals(true)<!>
const val equalsBoolean2 = false != true
const val equalsBoolean3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>false.equals(1)<!>
const val equalsBoolean4 = <!EQUALITY_NOT_APPLICABLE!>false == 1<!>
const val equalsChar1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>'1'.equals('2')<!>
const val equalsChar2 = '2' == '2'
const val equalsChar3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>'1'.equals(1)<!>
const val equalsChar4 = <!EQUALITY_NOT_APPLICABLE!>'1' == 1<!>
const val equalsByte1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.toByte().equals(2.toByte())<!>
const val equalsByte2 = 2.toByte() == 2.toByte()
const val equalsByte3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.toByte().equals("1")<!>
const val equalsByte4 = <!EQUALITY_NOT_APPLICABLE!>1.toByte() == "1"<!>
const val equalsShort1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.toShort().equals(2.toShort())<!>
const val equalsShort2 = 2.toShort() == 2.toShort()
const val equalsShort3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.toShort().equals("1")<!>
const val equalsShort4 = <!EQUALITY_NOT_APPLICABLE!>1.toShort() == "1"<!>
const val equalsInt1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.equals(2)<!>
const val equalsInt2 = 2 == 2
const val equalsInt3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.equals("1")<!>
const val equalsInt4 = <!EQUALITY_NOT_APPLICABLE!>1 == "1"<!>
const val equalsLong1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1L.equals(2L)<!>
const val equalsLong2 = 2L == 2L
const val equalsLong3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1L.equals("1")<!>
const val equalsLong4 = <!EQUALITY_NOT_APPLICABLE!>1L == "1"<!>
const val equalsFloat1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.0f.equals(2.0f)<!>
const val equalsFloat2 = 2.0f == 2.0f
const val equalsFloat3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.0f.equals("1")<!>
const val equalsFloat4 = <!EQUALITY_NOT_APPLICABLE!>1.0f == "1"<!>
const val equalsDoable1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.0.equals(2.0)<!>
const val equalsDoable2 = 2.0 == 2.0
const val equalsDoable3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>1.0.equals("1")<!>
const val equalsDoable4 = <!EQUALITY_NOT_APPLICABLE!>1.0 == "1"<!>
const val equalsString1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>"someStr".equals("123")<!>
const val equalsString2 = "someStr" == "otherStr"
const val equalsString3 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>"someStr".equals(1)<!>
const val equalsString4 = <!EQUALITY_NOT_APPLICABLE!>"someStr" == 1<!>
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !LANGUAGE: -IntrinsicConstEvaluation
const val equalsBoolean1 = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>true.equals(true)<!>
@@ -0,0 +1,3 @@
// ISSUE: KT-55196
const val bb: Boolean = !false // Red in K1, green in K2
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// ISSUE: KT-55196
const val bb: Boolean = <!CONST_VAL_WITH_NON_CONST_INITIALIZER!>!false<!> // Red in K1, green in K2
@@ -74,10 +74,10 @@ fun testArithmeticOperations() {
}
fun testLogicOperations() {
js("{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>!true<!>}; }")
js("{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>true or false<!>}; }")
js("{ var a = ${!true}; }")
js("{ var a = ${true or false}; }")
js("{ var a = ${true || false}; }")
js("{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>true and false<!>}; }")
js("{ var a = ${true and false}; }")
js("{ var a = ${true && false}; }")
js("{ var a = ${TRUE && false}; }")
@@ -85,14 +85,14 @@ fun testLogicOperations() {
}
fun testEq() {
js("{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>1 == 1<!>}; }")
js("{ var a = ${1 == 1}; }")
js(<!JSCODE_CAN_NOT_VERIFY_JAVASCRIPT!>"{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>1U == 1U<!>}; }"<!>)
js(<!JSCODE_CAN_NOT_VERIFY_JAVASCRIPT!>"{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>UONE == 1U<!>}; }"<!>)
js("{ var a = ${"FOO" == STR}; }")
js("{ var a = ${TRUE == null}; }")
js("{ var a = ${STR == null}; }")
js("{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>1 != 1<!>}; }")
js("{ var a = ${1 != 1}; }")
js(<!JSCODE_CAN_NOT_VERIFY_JAVASCRIPT!>"{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>1U != 1U<!>}; }"<!>)
js(<!JSCODE_CAN_NOT_VERIFY_JAVASCRIPT!>"{ var a = ${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>UONE != 1U<!>}; }"<!>)
js("{ var a = ${"FOO" != STR}; }")
@@ -23951,6 +23951,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/modifiers/const/arrayInAnnotationArgumentType.kt");
}
@Test
@TestMetadata("compare.kt")
public void testCompare() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/const/compare.kt");
}
@Test
@TestMetadata("constInteraction.kt")
public void testConstInteraction() throws Exception {