[FIR] Forbid complex boolean expressions

Disabling the language feature is supported,
otherwise there are too many tests that
would need to be updated to account for
K2's inability to do it.

The `ifConstVal.kt` test is deleted,
because now it must also be ignored in K2,
and since it is ignored for both the
frontends, and the ignored backends
include all the target backends, this test
is basically unused.

Note that now both the frontends report
`CONST_VAL_WITH_NON_CONST_INITIALIZER`.
for `condition`.

^KT-55196 Fixed
This commit is contained in:
Nikolay Lunyak
2023-08-16 11:00:26 +03:00
committed by Space Team
parent 79fe48ab5b
commit 73b4a81663
26 changed files with 69 additions and 200 deletions
@@ -795,6 +795,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/noUnusedOnDelegationWithProvider.kt");
}
@Test
@TestMetadata("nonConstNotCall.kt")
public void testNonConstNotCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/nonConstNotCall.kt");
}
@Test
@TestMetadata("Nullability.kt")
public void testNullability() throws Exception {
@@ -795,6 +795,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/noUnusedOnDelegationWithProvider.kt");
}
@Test
@TestMetadata("nonConstNotCall.kt")
public void testNonConstNotCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/nonConstNotCall.kt");
}
@Test
@TestMetadata("Nullability.kt")
public void testNullability() throws Exception {
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.isConst
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -76,7 +78,7 @@ internal fun checkConstantArguments(
}
expression is FirStringConcatenationCall || expression is FirEqualityOperatorCall -> {
for (exp in (expression as FirCall).arguments) {
if (exp is FirResolvedQualifier) {
if (exp is FirResolvedQualifier || expression.isForbiddenComplexConstant(session)) {
return ConstantArgumentKind.NOT_CONST
}
checkConstantArguments(exp, session)?.let { return it }
@@ -132,7 +134,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()) {
if (!symbol.canBeEvaluated() && !expression.isCompileTimeBuiltinCall() || expression.isForbiddenComplexConstant(session)) {
return ConstantArgumentKind.NOT_CONST
}
@@ -184,6 +186,30 @@ internal fun checkConstantArguments(
return null
}
private fun FirExpression.isForbiddenComplexConstant(session: FirSession): Boolean {
val forbidComplexBooleanExpressions = session.languageVersionSettings.supportsFeature(
LanguageFeature.ProhibitSimplificationOfNonTrivialConstBooleanExpressions
)
return isComplexBooleanConstant && forbidComplexBooleanExpressions
}
private val FirExpression.isComplexBooleanConstant
get(): Boolean = when {
!typeRef.coneType.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,
@@ -28904,12 +28904,6 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/involvesIrInterpreter/intrinsicConst/equals_after.kt");
}
@Test
@TestMetadata("ifConstVal.kt")
public void testIfConstVal() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/intrinsicConst/ifConstVal.kt");
}
@Test
@TestMetadata("kCallableName.kt")
public void testKCallableName() throws Exception {
@@ -28904,12 +28904,6 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/involvesIrInterpreter/intrinsicConst/equals_after.kt");
}
@Test
@TestMetadata("ifConstVal.kt")
public void testIfConstVal() throws Exception {
runTest("compiler/testData/codegen/box/involvesIrInterpreter/intrinsicConst/ifConstVal.kt");
}
@Test
@TestMetadata("kCallableName.kt")
public void testKCallableName() throws Exception {