Do not generate non-standard compareTo as primitive comparison in all backends
Previous changes related to this in the old JVM backend were in582b1c5e66and0482f7e9c5, but they did not affect the `ProperIeee754Comparisons` mode which became the default in 1.4.0. As a result, we had a regression here. Since the `PRIMITIVE_NUMERIC_COMPARISON_INFO` slice is used in psi2ir to determine how to generate the comparison, this fixes the regression both in the old JVM backend, and in all IR backends. #KT-41426 Fixed
This commit is contained in:
@@ -4104,15 +4104,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
TypeAndNullability right754Type = calcTypeForIeee754ArithmeticIfNeeded(right, getRightOperandType(primitiveNumericComparisonInfo));
|
TypeAndNullability right754Type = calcTypeForIeee754ArithmeticIfNeeded(right, getRightOperandType(primitiveNumericComparisonInfo));
|
||||||
boolean isSame754ArithmeticTypes = left754Type != null && right754Type != null && left754Type.type.equals(right754Type.type);
|
boolean isSame754ArithmeticTypes = left754Type != null && right754Type != null && left754Type.type.equals(right754Type.type);
|
||||||
boolean properIeee754Comparisons = shouldUseProperIeee754Comparisons();
|
boolean properIeee754Comparisons = shouldUseProperIeee754Comparisons();
|
||||||
|
boolean isStandardCompareTo = primitiveNumericComparisonInfo != null;
|
||||||
|
|
||||||
if (properIeee754Comparisons && left754Type != null && right754Type != null) {
|
if (properIeee754Comparisons && isStandardCompareTo && left754Type != null && right754Type != null) {
|
||||||
type = comparisonOperandType(left754Type.type, right754Type.type);
|
type = comparisonOperandType(left754Type.type, right754Type.type);
|
||||||
//type = comparisonOperandType(leftType, rightType);
|
|
||||||
leftValue = gen(left);
|
leftValue = gen(left);
|
||||||
rightValue = gen(right);
|
rightValue = gen(right);
|
||||||
}
|
}
|
||||||
else if (!properIeee754Comparisons &&
|
else if (!properIeee754Comparisons && isStandardCompareTo &&
|
||||||
state.getIntrinsics().getIntrinsic((FunctionDescriptor) resolvedCall.getResultingDescriptor()) instanceof CompareTo &&
|
|
||||||
((isPrimitive(leftType) && isPrimitive(rightType)) || isSame754ArithmeticTypes)) {
|
((isPrimitive(leftType) && isPrimitive(rightType)) || isSame754ArithmeticTypes)) {
|
||||||
type = isSame754ArithmeticTypes ? left754Type.type : comparisonOperandType(leftType, rightType);
|
type = isSame754ArithmeticTypes ? left754Type.type : comparisonOperandType(leftType, rightType);
|
||||||
leftValue = gen(left);
|
leftValue = gen(left);
|
||||||
|
|||||||
Generated
+5
@@ -18925,6 +18925,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
+9
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve.checkers
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
@@ -36,6 +37,8 @@ object PrimitiveNumericComparisonCallChecker : CallChecker {
|
|||||||
val binaryExpression = resolvedCall.call.callElement as? KtBinaryExpression ?: return
|
val binaryExpression = resolvedCall.call.callElement as? KtBinaryExpression ?: return
|
||||||
if (!comparisonOperatorTokens.contains(binaryExpression.operationReference.getReferencedNameElementType())) return
|
if (!comparisonOperatorTokens.contains(binaryExpression.operationReference.getReferencedNameElementType())) return
|
||||||
|
|
||||||
|
if (!resolvedCall.isStandardComparison()) return
|
||||||
|
|
||||||
val leftExpr = binaryExpression.left ?: return
|
val leftExpr = binaryExpression.left ?: return
|
||||||
val rightExpr = binaryExpression.right ?: return
|
val rightExpr = binaryExpression.right ?: return
|
||||||
|
|
||||||
@@ -68,6 +71,11 @@ object PrimitiveNumericComparisonCallChecker : CallChecker {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ResolvedCall<*>.isStandardComparison(): Boolean =
|
||||||
|
extensionReceiver == null &&
|
||||||
|
dispatchReceiver != null &&
|
||||||
|
KotlinBuiltIns.isUnderKotlinPackage(resultingDescriptor)
|
||||||
|
|
||||||
private fun leastCommonPrimitiveNumericType(t1: KotlinType, t2: KotlinType): KotlinType {
|
private fun leastCommonPrimitiveNumericType(t1: KotlinType, t2: KotlinType): KotlinType {
|
||||||
val pt1 = t1.promoteIntegerTypeToIntIfRequired()
|
val pt1 = t1.promoteIntegerTypeToIntIfRequired()
|
||||||
val pt2 = t2.promoteIntegerTypeToIntIfRequired()
|
val pt2 = t2.promoteIntegerTypeToIntIfRequired()
|
||||||
@@ -112,4 +120,4 @@ object PrimitiveNumericComparisonCallChecker : CallChecker {
|
|||||||
else ->
|
else ->
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
|
||||||
|
var longCompareToInvocations = 0
|
||||||
|
var doubleCompareToInvocations = 0
|
||||||
|
|
||||||
|
private operator fun Long?.compareTo(other: Long?): Int {
|
||||||
|
longCompareToInvocations++
|
||||||
|
val diff = (this ?: 0L) - (other ?: 0L)
|
||||||
|
return when {
|
||||||
|
diff < 0L -> -1
|
||||||
|
diff > 0L -> 1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private operator fun Double?.compareTo(other: Double?): Int {
|
||||||
|
doubleCompareToInvocations++
|
||||||
|
val diff = (this ?: 0.0) - (other ?: 0.0)
|
||||||
|
return when {
|
||||||
|
diff < 0.0 -> -1
|
||||||
|
diff > 0.0 -> 1
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkLong(): String? {
|
||||||
|
val a: Long? = null
|
||||||
|
val b: Long? = 42L
|
||||||
|
|
||||||
|
if (a > b) return "Fail Long >"
|
||||||
|
if (a >= b) return "Fail Long >="
|
||||||
|
if (!(a < b)) return "Fail Long <"
|
||||||
|
if (!(a <= b)) return "Fail Long <="
|
||||||
|
|
||||||
|
if (longCompareToInvocations != 4) return "Fail: expected 4 compareTo invocations, but was $longCompareToInvocations"
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkDouble(): String? {
|
||||||
|
val a: Double? = null
|
||||||
|
val b: Double? = 3.14
|
||||||
|
|
||||||
|
if (a > b) return "Fail Double >"
|
||||||
|
if (a >= b) return "Fail Double >="
|
||||||
|
if (!(a < b)) return "Fail Double <"
|
||||||
|
if (!(a <= b)) return "Fail Double <="
|
||||||
|
|
||||||
|
if (doubleCompareToInvocations != 4) return "Fail: expected 4 compareTo invocations, but was $doubleCompareToInvocations"
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkLong()?.let { return it }
|
||||||
|
checkDouble()?.let { return it }
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -20516,6 +20516,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
+5
@@ -20516,6 +20516,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
+5
@@ -18925,6 +18925,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
Generated
+5
@@ -15576,6 +15576,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
Generated
+5
@@ -15576,6 +15576,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
+5
@@ -15681,6 +15681,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/comparable.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("customCompareTo.kt")
|
||||||
|
public void testCustomCompareTo() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/customCompareTo.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("doubleInt.kt")
|
@TestMetadata("doubleInt.kt")
|
||||||
public void testDoubleInt() throws Exception {
|
public void testDoubleInt() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
runTest("compiler/testData/codegen/box/operatorConventions/compareTo/doubleInt.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user