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:
Dmitry Petrov
2017-07-06 17:11:21 +03:00
parent d137b04b0a
commit 9d1901fc7c
10 changed files with 130 additions and 20 deletions
@@ -174,26 +174,28 @@ fun isPrimitiveRangeContains(descriptor: CallableDescriptor): Boolean {
return true
}
fun isIntPrimitiveRangeExtensionForInt(descriptor: CallableDescriptor): Boolean {
fun isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(descriptor: CallableDescriptor): Boolean {
if (descriptor.name.asString() != "contains") 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
if (!isIntPrimitiveType(rangeElementType)) return false
val rangeElementType = getRangeOrProgressionElementType(extensionReceiverType) ?: return false
if (!isPrimitiveNumberType(rangeElementType)) return false
val argumentType = descriptor.valueParameters.singleOrNull()?.type ?: return false
if (!isIntPrimitiveType(argumentType)) return false
if (!isPrimitiveNumberType(argumentType)) return false
return true
}
private fun isIntPrimitiveType(type: KotlinType) =
private fun isPrimitiveNumberType(type: KotlinType) =
KotlinBuiltIns.isByte(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 {
if (descriptor.name.asString() != "contains") return false
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen.range
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.inExpression.CallBasedInExpressionGenerator
import org.jetbrains.kotlin.codegen.range.inExpression.InContinuousRangeExpressionGenerator
@@ -33,7 +32,7 @@ abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall<o
resolvedCallForIn.resultingDescriptor.let {
isPrimitiveRangeContains(it) ||
isClosedFloatingPointRangeContains(it) ||
isIntPrimitiveRangeExtensionForInt(it)
isPrimitiveNumberRangeExtensionContainsPrimitiveNumber(it)
}
override fun createIntrinsicInExpressionGenerator(