[FE 1.0] Report warning about new IL operator resolve in initializers and default values

^KT-48361 Fixed
This commit is contained in:
Dmitriy Novozhilov
2021-08-23 11:36:14 +03:00
committed by TeamCityServer
parent a15a5aa429
commit 40614507d3
29 changed files with 143 additions and 35 deletions
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.kotlin.resolve.DescriptorResolver.transformAnonymousTypeIfNeeded
import org.jetbrains.kotlin.resolve.calls.checkers.NewSchemeOfIntegerOperatorResolutionChecker
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
@@ -124,6 +125,13 @@ class VariableTypeAndInitializerResolver(
val initializer = variable.initializer
val initializerType =
expressionTypingServices.safeGetType(scope, initializer!!, variableType, dataFlowInfo, inferenceSession, trace)
NewSchemeOfIntegerOperatorResolutionChecker.checkArgument(
variableType,
initializer,
languageVersionSettings,
trace,
constantExpressionEvaluator.module
)
val constant = constantExpressionEvaluator.evaluateExpression(initializer, trace, initializerType)
?: return@computeInitializer null
@@ -131,7 +139,8 @@ class VariableTypeAndInitializerResolver(
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(initializer))
}
constant.toConstantValue(initializerType)
val qqq = constant.toConstantValue(initializerType)
qqq
},
null
)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
@@ -52,7 +53,14 @@ object NewSchemeOfIntegerOperatorResolutionChecker : CallChecker {
}
@JvmStatic
fun checkArgument(expectedType: KotlinType, argument: KtExpression, trace: BindingTrace, moduleDescriptor: ModuleDescriptor) {
fun checkArgument(
expectedType: KotlinType,
argument: KtExpression,
languageVersionSettings: LanguageVersionSettings,
trace: BindingTrace,
moduleDescriptor: ModuleDescriptor
) {
if (languageVersionSettings.supportsFeature(LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition)) return
val type = expectedType.lowerIfFlexible()
if (type.isPrimitiveNumberOrNullableType()) {
checkArgumentImpl(type, KtPsiUtil.deparenthesize(argument)!!, trace, moduleDescriptor)
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
@@ -47,6 +48,7 @@ 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 org.jetbrains.kotlin.utils.addToStdlib.runIf
import java.math.BigInteger
import java.util.*
@@ -379,7 +381,7 @@ private class ConstantExpressionEvaluatorVisitor(
private val languageVersionSettings = constantExpressionEvaluator.languageVersionSettings
private val builtIns = constantExpressionEvaluator.module.builtIns
private val defaultValueForDontCreateIntegerLiteralType =
languageVersionSettings.supportsFeature(LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition)
languageVersionSettings.supportsFeature(ApproximateIntegerLiteralTypesInReceiverPosition)
fun evaluate(expression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
val recordedCompileTimeConstant = ConstantExpressionEvaluator.getPossiblyErrorConstant(expression, trace.bindingContext)
@@ -666,10 +668,12 @@ private class ConstantExpressionEvaluatorVisitor(
val usesNonConstValAsConstant = usesNonConstValAsConstant(argumentForReceiver.expression)
val isNumberConversionMethod = resultingDescriptorName in OperatorConventions.NUMBER_CONVERSIONS
val isCharCode = argumentForReceiver.ctcType == CHAR && resultingDescriptorName == StandardNames.CHAR_CODE
val dontCreateILT = !isUnaryPlusMinus && !hasIntegerLiteralType(receiverExpression)
val dontCreateILT = defaultValueForDontCreateIntegerLiteralType &&
!isUnaryPlusMinus &&
!hasIntegerLiteralType(receiverExpression)
return createConstant(
result,
expectedType,
expectedType.takeUnless { dontCreateILT },
CompileTimeConstant.Parameters(
canBeUsedInAnnotation,
!isNumberConversionMethod && !isCharCode && isArgumentPure,
@@ -678,7 +682,7 @@ private class ConstantExpressionEvaluatorVisitor(
usesVariableAsConstant,
usesNonConstValAsConstant,
isConvertableConstVal = false,
dontCreateILT = defaultValueForDontCreateIntegerLiteralType && dontCreateILT
dontCreateILT = dontCreateILT
)
)
} else if (argumentsEntrySet.size == 1) {
@@ -713,6 +717,7 @@ private class ConstantExpressionEvaluatorVisitor(
usesVariableAsConstant(argumentForReceiver.expression) || usesVariableAsConstant(argumentForParameter.expression)
val usesNonConstValAsConstant =
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
val dontCreateILT = defaultValueForDontCreateIntegerLiteralType && !hasIntegerLiteralType(receiverExpression)
val parameters = CompileTimeConstant.Parameters(
canBeUsedInAnnotation,
areArgumentsPure,
@@ -721,13 +726,17 @@ private class ConstantExpressionEvaluatorVisitor(
usesVariableAsConstant,
usesNonConstValAsConstant,
isConvertableConstVal = false,
dontCreateILT = defaultValueForDontCreateIntegerLiteralType && !hasIntegerLiteralType(receiverExpression)
dontCreateILT = dontCreateILT
)
return when (resultingDescriptorName) {
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
OperatorNameConventions.EQUALS -> createCompileTimeConstantForEquals(result, callExpression)?.wrap(parameters)
else -> {
createConstant(result, expectedType, parameters)
createConstant(
result,
expectedType.takeUnless { dontCreateILT },
parameters
)
}
}
}
@@ -418,7 +418,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
DataFlowValue rightValue = components.dataFlowValueFactory.createDataFlowValue(right, rightType, context);
// We cannot say here anything new about rightValue except it has the same value as leftValue
resultInfo = resultInfo.replaceDataFlowInfo(dataFlowInfo.assign(leftValue, rightValue, components.languageVersionSettings));
NewSchemeOfIntegerOperatorResolutionChecker.checkArgument(expectedType, right, context.trace, components.moduleDescriptor);
NewSchemeOfIntegerOperatorResolutionChecker.checkArgument(expectedType, right, context.languageVersionSettings, context.trace, components.moduleDescriptor);
}
}
else {
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorResolver
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.checkers.NewSchemeOfIntegerOperatorResolutionChecker
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
@@ -71,6 +72,13 @@ class ValueParameterResolver(
val defaultValue = parameter.defaultValue ?: return
val type = valueParameterDescriptor.type
expressionTypingServices.getTypeInfo(defaultValue, context.replaceExpectedType(type))
NewSchemeOfIntegerOperatorResolutionChecker.checkArgument(
type,
defaultValue,
context.languageVersionSettings,
context.trace,
constantExpressionEvaluator.module
)
if (DescriptorUtils.isAnnotationClass(DescriptorResolver.getContainingClass(context.scope))) {
val constant = constantExpressionEvaluator.evaluateExpression(defaultValue, context.trace, type)
if ((constant == null || constant.usesNonConstValAsConstant) && !type.isError) {