[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:
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+1
-33
@@ -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
|
||||
|
||||
+5
-5
@@ -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}; }")
|
||||
|
||||
Generated
+6
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user