Deprecate simplification of complex boolean constant expressions in whens and loops

^KT-39883 In Progress
This commit is contained in:
Dmitriy Novozhilov
2021-06-25 11:40:51 +03:00
committed by teamcityserver
parent 8a2e0cedf9
commit 05883afc0a
36 changed files with 641 additions and 46 deletions
@@ -1028,7 +1028,7 @@ public interface Errors {
DiagnosticFactory0<KtConstantExpression> UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<KtExpression, KotlinType> INTEGER_OPERATOR_RESOLVE_WILL_CHANGE = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<KtExpression, Boolean> NON_TRIVIAL_BOOLEAN_CONSTANT = DiagnosticFactory1.create(WARNING);
// Casts and is-checks
@@ -439,6 +439,7 @@ public class DefaultErrorMessages {
MAP.put(UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH, "Type of the constant expression cannot be resolved. Please make sure you have the required dependencies for unsigned types in the classpath");
MAP.put(SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED, "Conversion of signed constants to unsigned ones is prohibited");
MAP.put(INTEGER_OPERATOR_RESOLVE_WILL_CHANGE, "This expression will be resolved to {0} in further releases. Please add explicit convention call", RENDER_TYPE);
MAP.put(NON_TRIVIAL_BOOLEAN_CONSTANT, "Compiler won't reduce this expression to {0} in future. Please replace it with boolean literal", TO_STRING);
MAP.put(RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS, "Left-hand side of callable reference matches expression syntax reserved for future releases");
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.isBoolean
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.math.BigInteger
@@ -387,12 +388,39 @@ private class ConstantExpressionEvaluatorVisitor(
val compileTimeConstant = expression.accept(this, expectedType ?: TypeUtils.NO_EXPECTED_TYPE)
if (compileTimeConstant != null) {
if (shouldSkipComplexBooleanValue(expression, compileTimeConstant)) {
return null
}
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant)
return compileTimeConstant
}
return null
}
@Suppress("warnings")
private fun shouldSkipComplexBooleanValue(
expression: KtExpression,
constant: CompileTimeConstant<*>
): Boolean {
if (constant.isError) return false
val constantValue = constant.toConstantValue(builtIns.booleanType)
if (!constantValue.getType(constantExpressionEvaluator.module).isBoolean()) return false
if (expression is KtConstantExpression || constant.parameters.usesVariableAsConstant) return false
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitSimplificationOfNonTrivialConstBooleanExpressions)) {
return true
} else {
val parent = expression.parent
if (
parent is KtWhenConditionWithExpression ||
parent is KtContainerNode && (parent.parent is KtWhileExpression || parent.parent is KtDoWhileExpression)
) {
trace.report(Errors.NON_TRIVIAL_BOOLEAN_CONSTANT.on(expression, constantValue.value as Boolean))
}
return false
}
}
private val stringExpressionEvaluator = object : KtVisitor<TypedCompileTimeConstant<String>, Nothing?>() {
private fun createStringConstant(compileTimeConstant: CompileTimeConstant<*>): TypedCompileTimeConstant<String>? {
val constantValue = compileTimeConstant.toConstantValue(TypeUtils.NO_EXPECTED_TYPE)