Intrinsify some mismatching range/element combinations for in/in!
It's safe to upcast integer types to Long,
floating-point types to Double.
So we don't have to create a range instance for cases such as
fun testLongInInt(x: Long, a: Int, b: Int) =
x in a .. b
which is equivalent to
fun testLongInInt(x: Long, a: Int, b: Int) =
x in a.toLong() .. b.toLong()
This commit is contained in:
@@ -174,26 +174,28 @@ fun isPrimitiveRangeContains(descriptor: CallableDescriptor): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isIntPrimitiveRangeExtensionForInt(descriptor: CallableDescriptor): Boolean {
|
fun isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(descriptor: CallableDescriptor): Boolean {
|
||||||
if (descriptor.name.asString() != "contains") return false
|
if (descriptor.name.asString() != "contains") return false
|
||||||
|
|
||||||
val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return false
|
val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return false
|
||||||
val extensionReceiverClassDescriptor = extensionReceiverType.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
|
||||||
if (!isTopLevelInPackage(extensionReceiverClassDescriptor, "ClosedRange", "kotlin.ranges")) return false
|
|
||||||
|
|
||||||
val rangeElementType = extensionReceiverType.arguments.singleOrNull()?.type ?: return false
|
val rangeElementType = getRangeOrProgressionElementType(extensionReceiverType) ?: return false
|
||||||
if (!isIntPrimitiveType(rangeElementType)) return false
|
if (!isPrimitiveNumberType(rangeElementType)) return false
|
||||||
|
|
||||||
val argumentType = descriptor.valueParameters.singleOrNull()?.type ?: return false
|
val argumentType = descriptor.valueParameters.singleOrNull()?.type ?: return false
|
||||||
if (!isIntPrimitiveType(argumentType)) return false
|
if (!isPrimitiveNumberType(argumentType)) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isIntPrimitiveType(type: KotlinType) =
|
private fun isPrimitiveNumberType(type: KotlinType) =
|
||||||
KotlinBuiltIns.isByte(type) ||
|
KotlinBuiltIns.isByte(type) ||
|
||||||
KotlinBuiltIns.isShort(type) ||
|
KotlinBuiltIns.isShort(type) ||
|
||||||
KotlinBuiltIns.isInt(type)
|
KotlinBuiltIns.isInt(type) ||
|
||||||
|
KotlinBuiltIns.isChar(type) ||
|
||||||
|
KotlinBuiltIns.isLong(type) ||
|
||||||
|
KotlinBuiltIns.isFloat(type) ||
|
||||||
|
KotlinBuiltIns.isDouble(type)
|
||||||
|
|
||||||
fun isClosedFloatingPointRangeContains(descriptor: CallableDescriptor): Boolean {
|
fun isClosedFloatingPointRangeContains(descriptor: CallableDescriptor): Boolean {
|
||||||
if (descriptor.name.asString() != "contains") return false
|
if (descriptor.name.asString() != "contains") return false
|
||||||
|
|||||||
+1
-2
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.codegen.range
|
package org.jetbrains.kotlin.codegen.range
|
||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.range.comparison.ComparisonGenerator
|
|
||||||
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
|
import org.jetbrains.kotlin.codegen.range.comparison.getComparisonGeneratorForRangeContainsCall
|
||||||
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
|
import org.jetbrains.kotlin.codegen.range.inExpression.CallBasedInExpressionGenerator
|
||||||
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
|
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
|
||||||
@@ -33,7 +32,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<o
|
|||||||
resolvedCallForIn.resultingDescriptor.let {
|
resolvedCallForIn.resultingDescriptor.let {
|
||||||
isPrimitiveRangeContains(it) ||
|
isPrimitiveRangeContains(it) ||
|
||||||
isClosedFloatingPointRangeContains(it) ||
|
isClosedFloatingPointRangeContains(it) ||
|
||||||
isIntPrimitiveRangeExtensionForInt(it)
|
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createIntrinsicInExpressionGenerator(
|
override fun createIntrinsicInExpressionGenerator(
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun inInt(x: Long): Boolean {
|
||||||
|
return x in 1..2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notInInt(x: Long): Boolean {
|
||||||
|
return x !in 1..2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun inLong(x: Int): Boolean {
|
||||||
|
return x in 1L..2L
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notInLong(x: Int): Boolean {
|
||||||
|
return x !in 1L..2L
|
||||||
|
}
|
||||||
|
|
||||||
|
fun inFloat(x: Double): Boolean {
|
||||||
|
return x in 1.0f..2.0f
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notInFloat(x: Double): Boolean {
|
||||||
|
return x !in 1.0f..2.0f
|
||||||
|
}
|
||||||
|
|
||||||
|
fun inDouble(x: Float): Boolean {
|
||||||
|
return x in 1.0..2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notInDouble(x: Float): Boolean {
|
||||||
|
return x !in 1.0..2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return when {
|
||||||
|
!inInt(1L) -> "Fail !inInt"
|
||||||
|
inInt(0L) -> "Fail inInt"
|
||||||
|
notInInt(1L) -> "Fail notInInt"
|
||||||
|
!notInInt(0L) -> "Fail !notInInt"
|
||||||
|
!inLong(1) -> "Fail !inLong"
|
||||||
|
inLong(0) -> "Fail inLong"
|
||||||
|
notInLong(1) -> "Fail notInLong"
|
||||||
|
!notInLong(0) -> "Fail !notInLong"
|
||||||
|
!inFloat(1.0) -> "Fain !inFloat"
|
||||||
|
inFloat(0.0) -> "Fain inFloat"
|
||||||
|
notInFloat(1.0) -> "Fail notInFloat"
|
||||||
|
!notInFloat(0.0) -> "Fail !notInFloat"
|
||||||
|
!inDouble(1.0F) -> "Fail !inDouble"
|
||||||
|
inDouble(0.0F) -> "Fail inDouble"
|
||||||
|
notInDouble(1.0F) -> "Fail notInDouble"
|
||||||
|
!notInDouble(0.0F) -> "Fail !notInDouble"
|
||||||
|
else -> "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-7
@@ -16,10 +16,12 @@ fun inDouble(x: Float): Boolean {
|
|||||||
return x in 1.0..2.0
|
return x in 1.0..2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 INVOKESPECIAL
|
// 3 I2L
|
||||||
// 2 NEW
|
// 3 F2D
|
||||||
// 2 INVOKESTATIC kotlin/ranges/RangesKt.rangeTo
|
// 0 INVOKESPECIAL
|
||||||
// 1 longRangeContains
|
// 0 NEW
|
||||||
// 1 intRangeContains
|
// 0 rangeTo
|
||||||
// 1 doubleRangeContains
|
// 0 longRangeContains
|
||||||
// 1 floatRangeContains
|
// 0 intRangeContains
|
||||||
|
// 0 doubleRangeContains
|
||||||
|
// 0 floatRangeContains
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
fun byteInFloat(x: Byte, a: Float, b: Float) = x in a .. b
|
||||||
|
fun byteInDouble(x: Byte, a: Double, b: Double) = x in a .. b
|
||||||
|
fun shortInFloat(x: Short, a: Float, b: Float) = x in a .. b
|
||||||
|
fun shortInDouble(x: Short, a: Double, b: Double) = x in a .. b
|
||||||
|
fun intInFloat(x: Int, a: Float, b: Float) = x in a .. b
|
||||||
|
fun intInDouble(x: Int, a: Double, b: Double) = x in a .. b
|
||||||
|
fun longInFloat(x: Long, a: Float, b: Float) = x in a .. b
|
||||||
|
fun longInDouble(x: Long, a: Double, b: Double) = x in a .. b
|
||||||
|
fun floatInInt(x: Float, a: Int, b: Int) = x in a .. b
|
||||||
|
fun floatInLong(x: Float, a: Long, b: Long) = x in a .. b
|
||||||
|
fun doubleInInt(x: Double, a: Int, b: Int) = x in a .. b
|
||||||
|
fun doubleInLong(x: Double, a: Long, b: Long) = x in a .. b
|
||||||
|
|
||||||
|
// 4 INVOKESPECIAL
|
||||||
|
// 4 NEW
|
||||||
|
// 8 rangeTo
|
||||||
|
// 2 longRangeContains
|
||||||
|
// 2 intRangeContains
|
||||||
|
// 4 doubleRangeContains
|
||||||
|
// 4 floatRangeContains
|
||||||
+6
@@ -13237,6 +13237,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inNonMatchingRange.kt")
|
||||||
|
public void testInNonMatchingRange() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inNonMatchingRange.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inOptimizableDoubleRange.kt")
|
@TestMetadata("inOptimizableDoubleRange.kt")
|
||||||
public void testInOptimizableDoubleRange() throws Exception {
|
public void testInOptimizableDoubleRange() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
||||||
|
|||||||
@@ -13237,6 +13237,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inNonMatchingRange.kt")
|
||||||
|
public void testInNonMatchingRange() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inNonMatchingRange.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inOptimizableDoubleRange.kt")
|
@TestMetadata("inOptimizableDoubleRange.kt")
|
||||||
public void testInOptimizableDoubleRange() throws Exception {
|
public void testInOptimizableDoubleRange() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
||||||
|
|||||||
@@ -1889,9 +1889,15 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("inNonMatchingRange.kt")
|
@TestMetadata("inNonMatchingRangeIntrinsified.kt")
|
||||||
public void testInNonMatchingRange() throws Exception {
|
public void testInNonMatchingRangeIntrinsified() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/ranges/inNonMatchingRange.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/ranges/inNonMatchingRangeIntrinsified.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inNonMatchingRangeNotIntrinsified.kt")
|
||||||
|
public void testInNonMatchingRangeNotIntrinsified() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/ranges/inNonMatchingRangeNotIntrinsified.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13237,6 +13237,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inNonMatchingRange.kt")
|
||||||
|
public void testInNonMatchingRange() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inNonMatchingRange.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inOptimizableDoubleRange.kt")
|
@TestMetadata("inOptimizableDoubleRange.kt")
|
||||||
public void testInOptimizableDoubleRange() throws Exception {
|
public void testInOptimizableDoubleRange() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
||||||
|
|||||||
@@ -14869,6 +14869,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inNonMatchingRange.kt")
|
||||||
|
public void testInNonMatchingRange() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inNonMatchingRange.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inOptimizableDoubleRange.kt")
|
@TestMetadata("inOptimizableDoubleRange.kt")
|
||||||
public void testInOptimizableDoubleRange() throws Exception {
|
public void testInOptimizableDoubleRange() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/contains/inOptimizableDoubleRange.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user