Implement new logic of approximation of integer literals in position of receiver
#KT-38895 In Progress
This commit is contained in:
committed by
TeamCityServer
parent
6afb905ad6
commit
bee2a69e21
+6
@@ -19087,6 +19087,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/numbers/literalReceiverWithIntegerValueType.kt");
|
runTest("compiler/testData/diagnostics/tests/numbers/literalReceiverWithIntegerValueType.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("newLiteralOperatorsResolution_newResolve.kt")
|
||||||
|
public void testNewLiteralOperatorsResolution_newResolve() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/numbers/newLiteralOperatorsResolution_newResolve.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("newLiteralOperatorsResolution_warning.kt")
|
@TestMetadata("newLiteralOperatorsResolution_warning.kt")
|
||||||
public void testNewLiteralOperatorsResolution_warning() throws Exception {
|
public void testNewLiteralOperatorsResolution_warning() throws Exception {
|
||||||
|
|||||||
+53
-18
@@ -279,9 +279,10 @@ class ConstantExpressionEvaluator(
|
|||||||
fun evaluateExpression(
|
fun evaluateExpression(
|
||||||
expression: KtExpression,
|
expression: KtExpression,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
expectedType: KotlinType? = TypeUtils.NO_EXPECTED_TYPE
|
expectedType: KotlinType? = TypeUtils.NO_EXPECTED_TYPE,
|
||||||
|
isIndependentContext: Boolean = false
|
||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*>? {
|
||||||
val visitor = ConstantExpressionEvaluatorVisitor(this, trace)
|
val visitor = ConstantExpressionEvaluatorVisitor(this, trace, isIndependentContext)
|
||||||
val constant = visitor.evaluate(expression, expectedType) ?: return null
|
val constant = visitor.evaluate(expression, expectedType) ?: return null
|
||||||
|
|
||||||
checkExperimentalityOfConstantLiteral(expression, constant, expectedType, trace)
|
checkExperimentalityOfConstantLiteral(expression, constant, expectedType, trace)
|
||||||
@@ -369,10 +370,12 @@ private val DIVISION_OPERATION_NAMES =
|
|||||||
|
|
||||||
private class ConstantExpressionEvaluatorVisitor(
|
private class ConstantExpressionEvaluatorVisitor(
|
||||||
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
private val constantExpressionEvaluator: ConstantExpressionEvaluator,
|
||||||
private val trace: BindingTrace
|
private val trace: BindingTrace,
|
||||||
|
private val isIndependentContext: Boolean
|
||||||
) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() {
|
) : KtVisitor<CompileTimeConstant<*>?, KotlinType>() {
|
||||||
private val languageVersionSettings = constantExpressionEvaluator.languageVersionSettings
|
private val languageVersionSettings = constantExpressionEvaluator.languageVersionSettings
|
||||||
private val builtIns = constantExpressionEvaluator.module.builtIns
|
private val builtIns = constantExpressionEvaluator.module.builtIns
|
||||||
|
private val defaultValueForDontCreateIntegerLiteralType = languageVersionSettings.supportsFeature(LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition)
|
||||||
|
|
||||||
fun evaluate(expression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
fun evaluate(expression: KtExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val recordedCompileTimeConstant = ConstantExpressionEvaluator.getPossiblyErrorConstant(expression, trace.bindingContext)
|
val recordedCompileTimeConstant = ConstantExpressionEvaluator.getPossiblyErrorConstant(expression, trace.bindingContext)
|
||||||
@@ -472,7 +475,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
isUnsignedLongNumberLiteral = isUnsignedLong,
|
isUnsignedLongNumberLiteral = isUnsignedLong,
|
||||||
usesVariableAsConstant = false,
|
usesVariableAsConstant = false,
|
||||||
usesNonConstValAsConstant = false,
|
usesNonConstValAsConstant = false,
|
||||||
isConvertableConstVal = false
|
isConvertableConstVal = false,
|
||||||
|
dontCreateILT = defaultValueForDontCreateIntegerLiteralType && isIndependentContext
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -522,7 +526,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
canBeUsedInAnnotation = canBeUsedInAnnotation,
|
canBeUsedInAnnotation = canBeUsedInAnnotation,
|
||||||
usesVariableAsConstant = usesVariableAsConstant,
|
usesVariableAsConstant = usesVariableAsConstant,
|
||||||
usesNonConstValAsConstant = usesNonConstantVariableAsConstant,
|
usesNonConstValAsConstant = usesNonConstantVariableAsConstant,
|
||||||
isConvertableConstVal = false
|
isConvertableConstVal = false,
|
||||||
|
dontCreateILT = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else null
|
else null
|
||||||
@@ -586,7 +591,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
isUnsignedLongNumberLiteral = false,
|
isUnsignedLongNumberLiteral = false,
|
||||||
usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant,
|
usesVariableAsConstant = leftConstant.usesVariableAsConstant || rightConstant.usesVariableAsConstant,
|
||||||
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant,
|
usesNonConstValAsConstant = leftConstant.usesNonConstValAsConstant || rightConstant.usesNonConstValAsConstant,
|
||||||
isConvertableConstVal = false
|
isConvertableConstVal = false,
|
||||||
|
dontCreateILT = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -605,7 +611,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
private fun evaluateCall(
|
private fun evaluateCall(
|
||||||
callExpression: KtExpression,
|
callExpression: KtExpression,
|
||||||
receiverExpression: KtExpression,
|
receiverExpression: KtExpression,
|
||||||
expectedType: KotlinType?
|
expectedType: KotlinType?,
|
||||||
|
isUnaryPlusMinus: Boolean = false
|
||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*>? {
|
||||||
val resolvedCall = callExpression.getResolvedCall(trace.bindingContext) ?: return null
|
val resolvedCall = callExpression.getResolvedCall(trace.bindingContext) ?: return null
|
||||||
if (!KotlinBuiltIns.isUnderKotlinPackage(resolvedCall.resultingDescriptor)) return null
|
if (!KotlinBuiltIns.isUnderKotlinPackage(resolvedCall.resultingDescriptor)) return null
|
||||||
@@ -632,9 +639,12 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
CompileTimeConstant.Parameters(
|
CompileTimeConstant.Parameters(
|
||||||
canBeUsedInAnnotation,
|
canBeUsedInAnnotation,
|
||||||
!isNumberConversionMethod && isArgumentPure,
|
!isNumberConversionMethod && isArgumentPure,
|
||||||
false, false,
|
isUnsignedNumberLiteral = false,
|
||||||
usesVariableAsConstant, usesNonConstValAsConstant,
|
isUnsignedLongNumberLiteral = false,
|
||||||
false
|
usesVariableAsConstant,
|
||||||
|
usesNonConstValAsConstant,
|
||||||
|
isConvertableConstVal = false,
|
||||||
|
dontCreateILT = !isUnaryPlusMinus && defaultValueForDontCreateIntegerLiteralType && !hasIntegerLiteralType(receiverExpression)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else if (argumentsEntrySet.size == 1) {
|
} else if (argumentsEntrySet.size == 1) {
|
||||||
@@ -667,7 +677,14 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
val usesNonConstValAsConstant =
|
val usesNonConstValAsConstant =
|
||||||
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
|
usesNonConstValAsConstant(argumentForReceiver.expression) || usesNonConstValAsConstant(argumentForParameter.expression)
|
||||||
val parameters = CompileTimeConstant.Parameters(
|
val parameters = CompileTimeConstant.Parameters(
|
||||||
canBeUsedInAnnotation, areArgumentsPure, false, false, usesVariableAsConstant, usesNonConstValAsConstant, false
|
canBeUsedInAnnotation,
|
||||||
|
areArgumentsPure,
|
||||||
|
isUnsignedNumberLiteral = false,
|
||||||
|
isUnsignedLongNumberLiteral = false,
|
||||||
|
usesVariableAsConstant,
|
||||||
|
usesNonConstValAsConstant,
|
||||||
|
isConvertableConstVal = false,
|
||||||
|
dontCreateILT = defaultValueForDontCreateIntegerLiteralType && !hasIntegerLiteralType(receiverExpression)
|
||||||
)
|
)
|
||||||
return when (resultingDescriptorName) {
|
return when (resultingDescriptorName) {
|
||||||
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
|
OperatorNameConventions.COMPARE_TO -> createCompileTimeConstantForCompareTo(result, callExpression)?.wrap(parameters)
|
||||||
@@ -693,6 +710,9 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
private fun isPureConstant(expression: KtExpression) =
|
private fun isPureConstant(expression: KtExpression) =
|
||||||
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.isPure ?: false
|
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.isPure ?: false
|
||||||
|
|
||||||
|
private fun hasIntegerLiteralType(expression: KtExpression): Boolean =
|
||||||
|
ConstantExpressionEvaluator.getConstant(expression, trace.bindingContext)?.hasIntegerLiteralType ?: false
|
||||||
|
|
||||||
private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: KtExpression): Any? {
|
private fun evaluateUnaryAndCheck(receiver: OperationArgument, name: String, callExpression: KtExpression): Any? {
|
||||||
return evaluateUnaryAndCheck(name, receiver.ctcType, receiver.value) {
|
return evaluateUnaryAndCheck(name, receiver.ctcType, receiver.value) {
|
||||||
trace.report(Errors.INTEGER_OVERFLOW.on(callExpression.getStrictParentOfType<KtExpression>() ?: callExpression))
|
trace.report(Errors.INTEGER_OVERFLOW.on(callExpression.getStrictParentOfType<KtExpression>() ?: callExpression))
|
||||||
@@ -716,8 +736,13 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
|
|
||||||
override fun visitUnaryExpression(expression: KtUnaryExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitUnaryExpression(expression: KtUnaryExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
val leftExpression = expression.baseExpression ?: return null
|
val leftExpression = expression.baseExpression ?: return null
|
||||||
|
val tokenType = expression.operationToken
|
||||||
return evaluateCall(expression.operationReference, leftExpression, expectedType)
|
return evaluateCall(
|
||||||
|
expression.operationReference,
|
||||||
|
leftExpression,
|
||||||
|
expectedType,
|
||||||
|
isUnaryPlusMinus = tokenType == KtTokens.PLUS || tokenType == KtTokens.MINUS
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, expectedType: KotlinType?): CompileTimeConstant<*>? {
|
||||||
@@ -747,7 +772,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
isUnsignedLongNumberLiteral = false,
|
isUnsignedLongNumberLiteral = false,
|
||||||
usesVariableAsConstant = true,
|
usesVariableAsConstant = true,
|
||||||
usesNonConstValAsConstant = !callableDescriptor.isConst,
|
usesNonConstValAsConstant = !callableDescriptor.isConst,
|
||||||
isConvertableConstVal = isConvertableConstVal
|
isConvertableConstVal = isConvertableConstVal,
|
||||||
|
dontCreateILT = true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -981,7 +1007,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
value: Long,
|
value: Long,
|
||||||
parameters: CompileTimeConstant.Parameters,
|
parameters: CompileTimeConstant.Parameters,
|
||||||
expectedType: KotlinType
|
expectedType: KotlinType
|
||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*> {
|
||||||
if (parameters.isUnsignedNumberLiteral && !checkAccessibilityOfUnsignedTypes()) {
|
if (parameters.isUnsignedNumberLiteral && !checkAccessibilityOfUnsignedTypes()) {
|
||||||
return UnsignedErrorValueTypeConstant(value, parameters)
|
return UnsignedErrorValueTypeConstant(value, parameters)
|
||||||
}
|
}
|
||||||
@@ -991,7 +1017,9 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
|
if (TypeUtils.noExpectedType(expectedType) || expectedType.isError) {
|
||||||
return createIntegerValueTypeConstant(
|
return if (parameters.dontCreateILT) {
|
||||||
|
value.createSimpleIntCompileTimeConst(parameters)
|
||||||
|
} else createIntegerValueTypeConstant(
|
||||||
value,
|
value,
|
||||||
constantExpressionEvaluator.module,
|
constantExpressionEvaluator.module,
|
||||||
parameters,
|
parameters,
|
||||||
@@ -1005,6 +1033,11 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
return integerValue.wrap(parameters)
|
return integerValue.wrap(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return value.createSimpleIntCompileTimeConst(parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Long.createSimpleIntCompileTimeConst(parameters: CompileTimeConstant.Parameters): TypedCompileTimeConstant<*> {
|
||||||
|
val value = this
|
||||||
return if (parameters.isUnsignedNumberLiteral) {
|
return if (parameters.isUnsignedNumberLiteral) {
|
||||||
when (value) {
|
when (value) {
|
||||||
value.toInt().fromUIntToLong() -> UIntValue(value.toInt())
|
value.toInt().fromUIntToLong() -> UIntValue(value.toInt())
|
||||||
@@ -1035,7 +1068,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
isUnsignedLong: Boolean = false,
|
isUnsignedLong: Boolean = false,
|
||||||
usesVariableAsConstant: Boolean = false,
|
usesVariableAsConstant: Boolean = false,
|
||||||
usesNonConstValAsConstant: Boolean = false,
|
usesNonConstValAsConstant: Boolean = false,
|
||||||
isConvertableConstVal: Boolean = false
|
isConvertableConstVal: Boolean = false,
|
||||||
|
dontCreateILT: Boolean = false
|
||||||
): TypedCompileTimeConstant<T> =
|
): TypedCompileTimeConstant<T> =
|
||||||
wrap(
|
wrap(
|
||||||
CompileTimeConstant.Parameters(
|
CompileTimeConstant.Parameters(
|
||||||
@@ -1045,7 +1079,8 @@ private class ConstantExpressionEvaluatorVisitor(
|
|||||||
isUnsignedLong,
|
isUnsignedLong,
|
||||||
usesVariableAsConstant,
|
usesVariableAsConstant,
|
||||||
usesNonConstValAsConstant,
|
usesNonConstValAsConstant,
|
||||||
isConvertableConstVal
|
isConvertableConstVal,
|
||||||
|
dontCreateILT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-5
@@ -172,7 +172,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
KotlinTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, null, null, context);
|
KotlinTypeInfo typeInfo = callExpressionResolver.getSimpleNameExpressionTypeInfo(expression, null, null, context);
|
||||||
checkNull(expression, context, typeInfo.getType());
|
checkNull(expression, context, typeInfo.getType());
|
||||||
|
|
||||||
components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, context.expectedType);
|
components.constantExpressionEvaluator.evaluateExpression(
|
||||||
|
expression, context.trace, context.expectedType, evaluateIntegerConstantInIndependentMode(context)
|
||||||
|
);
|
||||||
return components.dataFlowAnalyzer.checkType(typeInfo, expression, context); // TODO : Extensions to this
|
return components.dataFlowAnalyzer.checkType(typeInfo, expression, context); // TODO : Extensions to this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +209,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompileTimeConstant<?> compileTimeConstant = components.constantExpressionEvaluator.evaluateExpression(
|
CompileTimeConstant<?> compileTimeConstant = components.constantExpressionEvaluator.evaluateExpression(
|
||||||
expression, context.trace, context.expectedType
|
expression, context.trace, context.expectedType, evaluateIntegerConstantInIndependentMode(context)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (compileTimeConstant instanceof UnsignedErrorValueTypeConstant) {
|
if (compileTimeConstant instanceof UnsignedErrorValueTypeConstant) {
|
||||||
@@ -793,7 +795,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
|
CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
|
||||||
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
|
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType, evaluateIntegerConstantInIndependentMode(context)
|
||||||
);
|
);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
||||||
@@ -1086,7 +1088,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
result = TypeInfoFactoryKt.noTypeInfo(context);
|
result = TypeInfoFactoryKt.noTypeInfo(context);
|
||||||
}
|
}
|
||||||
CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
|
CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(
|
||||||
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType
|
expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType, evaluateIntegerConstantInIndependentMode(context)
|
||||||
);
|
);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
|
||||||
@@ -1595,7 +1597,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
for (KtStringTemplateEntry entry : expression.getEntries()) {
|
for (KtStringTemplateEntry entry : expression.getEntries()) {
|
||||||
entry.accept(visitor);
|
entry.accept(visitor);
|
||||||
}
|
}
|
||||||
components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, contextWithExpectedType.expectedType);
|
components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, contextWithExpectedType.expectedType, evaluateIntegerConstantInIndependentMode(context));
|
||||||
return components.dataFlowAnalyzer.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
|
return components.dataFlowAnalyzer.checkType(visitor.typeInfo.replaceType(components.builtIns.getStringType()),
|
||||||
expression,
|
expression,
|
||||||
contextWithExpectedType);
|
contextWithExpectedType);
|
||||||
@@ -1798,4 +1800,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return BindingContextUtils.getRecordedTypeInfo(expression, context.trace.getBindingContext());
|
return BindingContextUtils.getRecordedTypeInfo(expression, context.trace.getBindingContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean evaluateIntegerConstantInIndependentMode(ExpressionTypingContext context) {
|
||||||
|
return context.contextDependency == INDEPENDENT && context.languageVersionSettings.supportsFeature(LanguageFeature.ApproximateIntegerLiteralTypesInReceiverPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+116
@@ -0,0 +1,116 @@
|
|||||||
|
// LANGUAGE: +ApproximateIntegerLiteralTypesInReceiverPosition
|
||||||
|
// WITH_STDLIB
|
||||||
|
// ISSUE: KT-38895
|
||||||
|
|
||||||
|
fun takeByte(b: Byte) {}
|
||||||
|
fun takeInt(b: Int) {}
|
||||||
|
fun takeLong(b: Long) {}
|
||||||
|
|
||||||
|
fun testByteBinaryOperators() {
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 + 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 - 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 * 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 / 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 % 1<!>)
|
||||||
|
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.plus(1)<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.minus(1)<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.times(1)<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.div(1)<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.rem(1)<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 shl 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 shr 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 ushr 1<!>)
|
||||||
|
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 and 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 or 1<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2 xor 1<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testByteUnaryOperators() {
|
||||||
|
// No mismatch
|
||||||
|
takeByte(+1)
|
||||||
|
takeByte(-1)
|
||||||
|
|
||||||
|
// Mismatch
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.unaryPlus()<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.unaryMinus()<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>2.inv()<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>1.inc()<!>)
|
||||||
|
takeByte(<!ARGUMENT_TYPE_MISMATCH!>1.dec()<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLongBinaryOperators() {
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 + 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 - 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 * 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 / 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 % 1<!>)
|
||||||
|
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.plus(1)<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.minus(1)<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.times(1)<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.div(1)<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.rem(1)<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 shl 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 shr 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 ushr 1<!>)
|
||||||
|
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 and 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 or 1<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2 xor 1<!>)
|
||||||
|
|
||||||
|
// positive
|
||||||
|
takeLong(2 * 100000000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLongUnaryOperators() {
|
||||||
|
// No mismatch
|
||||||
|
takeLong(+1)
|
||||||
|
takeLong(-1)
|
||||||
|
|
||||||
|
// Mismatch
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.unaryPlus()<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.unaryMinus()<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>2.inv()<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>1.inc()<!>)
|
||||||
|
takeLong(<!ARGUMENT_TYPE_MISMATCH!>1.dec()<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntBinaryOperators() {
|
||||||
|
takeInt(2 + 1)
|
||||||
|
takeInt(2 - 1)
|
||||||
|
takeInt(2 * 1)
|
||||||
|
takeInt(2 / 1)
|
||||||
|
takeInt(2 % 1)
|
||||||
|
|
||||||
|
takeInt(2.plus(1))
|
||||||
|
takeInt(2.minus(1))
|
||||||
|
takeInt(2.times(1))
|
||||||
|
takeInt(2.div(1))
|
||||||
|
takeInt(2.rem(1))
|
||||||
|
takeInt(2 shl 1)
|
||||||
|
takeInt(2 shr 1)
|
||||||
|
takeInt(2 ushr 1)
|
||||||
|
|
||||||
|
takeInt(2 and 1)
|
||||||
|
takeInt(2 or 1)
|
||||||
|
takeInt(2 xor 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntUnaryOperators() {
|
||||||
|
takeInt(+1)
|
||||||
|
takeInt(-1)
|
||||||
|
|
||||||
|
takeInt(2.unaryPlus())
|
||||||
|
takeInt(2.unaryMinus())
|
||||||
|
takeInt(2.inv())
|
||||||
|
takeInt(1.inc())
|
||||||
|
takeInt(1.dec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNoOperators() {
|
||||||
|
takeByte(1)
|
||||||
|
takeInt(1)
|
||||||
|
takeLong(1)
|
||||||
|
}
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
// LANGUAGE: +ApproximateIntegerLiteralTypesInReceiverPosition
|
||||||
|
// WITH_STDLIB
|
||||||
|
// ISSUE: KT-38895
|
||||||
|
|
||||||
|
fun takeByte(b: Byte) {}
|
||||||
|
fun takeInt(b: Int) {}
|
||||||
|
fun takeLong(b: Long) {}
|
||||||
|
|
||||||
|
fun testByteBinaryOperators() {
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 + 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 - 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 * 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 / 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 % 1<!>)
|
||||||
|
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.plus(1)<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.minus(1)<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.times(1)<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.div(1)<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.rem(1)<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 shl 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 shr 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 ushr 1<!>)
|
||||||
|
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 and 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 or 1<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2 xor 1<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testByteUnaryOperators() {
|
||||||
|
// No mismatch
|
||||||
|
takeByte(+1)
|
||||||
|
takeByte(-1)
|
||||||
|
|
||||||
|
// Mismatch
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.unaryPlus()<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.unaryMinus()<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>2.inv()<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>1.inc()<!>)
|
||||||
|
takeByte(<!TYPE_MISMATCH!>1.dec()<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLongBinaryOperators() {
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 + 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 - 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 * 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 / 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 % 1<!>)
|
||||||
|
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.plus(1)<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.minus(1)<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.times(1)<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.div(1)<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.rem(1)<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 shl 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 shr 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 ushr 1<!>)
|
||||||
|
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 and 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 or 1<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2 xor 1<!>)
|
||||||
|
|
||||||
|
// positive
|
||||||
|
takeLong(2 * 100000000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testLongUnaryOperators() {
|
||||||
|
// No mismatch
|
||||||
|
takeLong(+1)
|
||||||
|
takeLong(-1)
|
||||||
|
|
||||||
|
// Mismatch
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.unaryPlus()<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.unaryMinus()<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>2.inv()<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>1.inc()<!>)
|
||||||
|
takeLong(<!TYPE_MISMATCH!>1.dec()<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntBinaryOperators() {
|
||||||
|
takeInt(2 + 1)
|
||||||
|
takeInt(2 - 1)
|
||||||
|
takeInt(2 * 1)
|
||||||
|
takeInt(2 / 1)
|
||||||
|
takeInt(2 % 1)
|
||||||
|
|
||||||
|
takeInt(2.plus(1))
|
||||||
|
takeInt(2.minus(1))
|
||||||
|
takeInt(2.times(1))
|
||||||
|
takeInt(2.div(1))
|
||||||
|
takeInt(2.rem(1))
|
||||||
|
takeInt(2 shl 1)
|
||||||
|
takeInt(2 shr 1)
|
||||||
|
takeInt(2 ushr 1)
|
||||||
|
|
||||||
|
takeInt(2 and 1)
|
||||||
|
takeInt(2 or 1)
|
||||||
|
takeInt(2 xor 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testIntUnaryOperators() {
|
||||||
|
takeInt(+1)
|
||||||
|
takeInt(-1)
|
||||||
|
|
||||||
|
takeInt(2.unaryPlus())
|
||||||
|
takeInt(2.unaryMinus())
|
||||||
|
takeInt(2.inv())
|
||||||
|
takeInt(1.inc())
|
||||||
|
takeInt(1.dec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNoOperators() {
|
||||||
|
takeByte(1)
|
||||||
|
takeInt(1)
|
||||||
|
takeLong(1)
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun takeByte(/*0*/ b: kotlin.Byte): kotlin.Unit
|
||||||
|
public fun takeInt(/*0*/ b: kotlin.Int): kotlin.Unit
|
||||||
|
public fun takeLong(/*0*/ b: kotlin.Long): kotlin.Unit
|
||||||
|
public fun testByteBinaryOperators(): kotlin.Unit
|
||||||
|
public fun testByteUnaryOperators(): kotlin.Unit
|
||||||
|
public fun testIntBinaryOperators(): kotlin.Unit
|
||||||
|
public fun testIntUnaryOperators(): kotlin.Unit
|
||||||
|
public fun testLongBinaryOperators(): kotlin.Unit
|
||||||
|
public fun testLongUnaryOperators(): kotlin.Unit
|
||||||
|
public fun testNoOperators(): kotlin.Unit
|
||||||
Generated
+6
@@ -19093,6 +19093,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/numbers/literalReceiverWithIntegerValueType.kt");
|
runTest("compiler/testData/diagnostics/tests/numbers/literalReceiverWithIntegerValueType.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("newLiteralOperatorsResolution_newResolve.kt")
|
||||||
|
public void testNewLiteralOperatorsResolution_newResolve() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/numbers/newLiteralOperatorsResolution_newResolve.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("newLiteralOperatorsResolution_warning.kt")
|
@TestMetadata("newLiteralOperatorsResolution_warning.kt")
|
||||||
public void testNewLiteralOperatorsResolution_warning() throws Exception {
|
public void testNewLiteralOperatorsResolution_warning() throws Exception {
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ class ConstraintSystemTestData(
|
|||||||
val matcher = INTEGER_VALUE_TYPE_PATTERN.matcher(name)
|
val matcher = INTEGER_VALUE_TYPE_PATTERN.matcher(name)
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
val number = matcher.group(1)!!
|
val number = matcher.group(1)!!
|
||||||
val parameters = CompileTimeConstant.Parameters(false, false, false, false, false, false, false)
|
val parameters = CompileTimeConstant.Parameters(false, false, false, false, false, false, false, false)
|
||||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
IntegerValueTypeConstructor(number.toLong(), functionFoo.module, parameters),
|
IntegerValueTypeConstructor(number.toLong(), functionFoo.module, parameters),
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ interface CompileTimeConstant<out T> {
|
|||||||
|
|
||||||
val isUnsignedNumberLiteral: Boolean get() = parameters.isUnsignedNumberLiteral
|
val isUnsignedNumberLiteral: Boolean get() = parameters.isUnsignedNumberLiteral
|
||||||
|
|
||||||
|
val hasIntegerLiteralType: Boolean
|
||||||
|
|
||||||
data class Parameters(
|
data class Parameters(
|
||||||
val canBeUsedInAnnotation: Boolean,
|
val canBeUsedInAnnotation: Boolean,
|
||||||
val isPure: Boolean,
|
val isPure: Boolean,
|
||||||
@@ -56,7 +58,8 @@ interface CompileTimeConstant<out T> {
|
|||||||
val usesVariableAsConstant: Boolean,
|
val usesVariableAsConstant: Boolean,
|
||||||
val usesNonConstValAsConstant: Boolean,
|
val usesNonConstValAsConstant: Boolean,
|
||||||
// `isConvertableConstVal` means that this is `const val` that has `ImplicitIntegerCoercion` annotation
|
// `isConvertableConstVal` means that this is `const val` that has `ImplicitIntegerCoercion` annotation
|
||||||
val isConvertableConstVal: Boolean
|
val isConvertableConstVal: Boolean,
|
||||||
|
val dontCreateILT: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean
|
override fun equals(other: Any?): Boolean
|
||||||
@@ -90,6 +93,9 @@ class TypedCompileTimeConstant<out T>(
|
|||||||
result = 31 * result + type.hashCode()
|
result = 31 * result + type.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val hasIntegerLiteralType: Boolean
|
||||||
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createIntegerValueTypeConstant(
|
fun createIntegerValueTypeConstant(
|
||||||
@@ -120,6 +126,9 @@ class UnsignedErrorValueTypeConstant(
|
|||||||
override fun equals(other: Any?) = other is UnsignedErrorValueTypeConstant && value == other.value
|
override fun equals(other: Any?) = other is UnsignedErrorValueTypeConstant && value == other.value
|
||||||
|
|
||||||
override fun hashCode() = value.hashCode()
|
override fun hashCode() = value.hashCode()
|
||||||
|
|
||||||
|
override val hasIntegerLiteralType: Boolean
|
||||||
|
get() = false
|
||||||
}
|
}
|
||||||
|
|
||||||
class IntegerValueTypeConstant(
|
class IntegerValueTypeConstant(
|
||||||
@@ -139,7 +148,8 @@ class IntegerValueTypeConstant(
|
|||||||
isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral,
|
isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral,
|
||||||
usesVariableAsConstant = parameters.usesVariableAsConstant,
|
usesVariableAsConstant = parameters.usesVariableAsConstant,
|
||||||
usesNonConstValAsConstant = parameters.usesNonConstValAsConstant,
|
usesNonConstValAsConstant = parameters.usesNonConstValAsConstant,
|
||||||
isConvertableConstVal = parameters.isConvertableConstVal
|
isConvertableConstVal = parameters.isConvertableConstVal,
|
||||||
|
dontCreateILT = false
|
||||||
)
|
)
|
||||||
|
|
||||||
return IntegerValueTypeConstant(value, module, newParameters, newInferenceEnabled, convertedFromSigned = true)
|
return IntegerValueTypeConstant(value, module, newParameters, newInferenceEnabled, convertedFromSigned = true)
|
||||||
@@ -153,7 +163,8 @@ class IntegerValueTypeConstant(
|
|||||||
isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral,
|
isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral,
|
||||||
usesVariableAsConstant = parameters.usesVariableAsConstant,
|
usesVariableAsConstant = parameters.usesVariableAsConstant,
|
||||||
usesNonConstValAsConstant = parameters.usesNonConstValAsConstant,
|
usesNonConstValAsConstant = parameters.usesNonConstValAsConstant,
|
||||||
isConvertableConstVal = parameters.isConvertableConstVal
|
isConvertableConstVal = parameters.isConvertableConstVal,
|
||||||
|
dontCreateILT = false
|
||||||
)
|
)
|
||||||
|
|
||||||
return IntegerValueTypeConstant(value, module, newParameters, newInferenceEnabled, convertedFromSigned = true)
|
return IntegerValueTypeConstant(value, module, newParameters, newInferenceEnabled, convertedFromSigned = true)
|
||||||
@@ -202,4 +213,6 @@ class IntegerValueTypeConstant(
|
|||||||
|
|
||||||
override fun hashCode() = 31 * value.hashCode() + parameters.hashCode()
|
override fun hashCode() = 31 * value.hashCode() + parameters.hashCode()
|
||||||
|
|
||||||
|
override val hasIntegerLiteralType: Boolean
|
||||||
|
get() = true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user