diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt index 50be6a87f39..af889eaf756 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/RangeCodegenUtil.kt @@ -49,10 +49,10 @@ private val PROGRESSION_TO_ELEMENT_TYPE: Map = fun supportedRangeTypes() = listOf(PrimitiveType.CHAR, PrimitiveType.INT, PrimitiveType.LONG) -fun isRange(rangeType: KotlinType) = +fun isPrimitiveRange(rangeType: KotlinType) = !rangeType.isMarkedNullable && getPrimitiveRangeElementType(rangeType) != null -fun isProgression(rangeType: KotlinType) = +fun isPrimitiveProgression(rangeType: KotlinType) = !rangeType.isMarkedNullable && getPrimitiveProgressionElementType(rangeType) != null fun getPrimitiveRangeElementType(rangeType: KotlinType) = diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt index 3b81d96f115..6d540e610e5 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValue.kt @@ -18,9 +18,11 @@ package org.jetbrains.kotlin.codegen.range import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.forLoop.* +import org.jetbrains.kotlin.codegen.isPrimitiveRange import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall interface RangeValue { @@ -69,53 +71,71 @@ class IterableRangeValue : RangeValue { CallBasedInExpressionGenerator(codegen, operatorReference) } -abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall): RangeValue +abstract class CallIntrinsicRangeValue(protected val rangeCall: ResolvedCall): RangeValue { + protected abstract fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall): Boolean -class PrimitiveNumberRangeLiteralRangeValue(loopRangeCall: ResolvedCall): CallIntrinsicRangeValue(loopRangeCall) { + protected abstract fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator + + override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator { + val resolvedCall = operatorReference.getResolvedCallWithAssert(codegen.bindingContext) + return if (isIntrinsicInCall(resolvedCall)) + createIntrinsicInExpressionGenerator(codegen, operatorReference) + else + CallBasedInExpressionGenerator(codegen, operatorReference) + } +} + +abstract class PrimitiveNumberRangeIntrinsicRangeValue(rangeCall: ResolvedCall): CallIntrinsicRangeValue(rangeCall) { + override fun isIntrinsicInCall(resolvedCallForIn: ResolvedCall): Boolean = + resolvedCallForIn.resultingDescriptor.dispatchReceiverParameter?.let { + isPrimitiveRange(it.type) + } ?: false +} + +class PrimitiveNumberRangeLiteralRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInRangeLiteralLoopGenerator(codegen, forExpression, rangeCall) - override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = + override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = InPrimitiveNumberRangeLiteralGenerator(codegen, operatorReference, rangeCall) } -class DownToProgressionRangeValue(loopRangeCall: ResolvedCall): CallIntrinsicRangeValue(loopRangeCall) { +class DownToProgressionRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInDownToProgressionLoopGenerator(codegen, forExpression, rangeCall) - override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = + override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = InPrimitiveNumberDownToGenerator(codegen, operatorReference, rangeCall) } -class PrimitiveNumberUntilRangeValue(loopRangeCall: ResolvedCall): CallIntrinsicRangeValue(loopRangeCall) { +class PrimitiveNumberUntilRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInUntilRangeLoopGenerator(codegen, forExpression, rangeCall) - override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = + override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = InPrimitiveNumberUntilGenerator(codegen, operatorReference, rangeCall) } -class ArrayIndicesRangeValue(loopRangeCall: ResolvedCall): CallIntrinsicRangeValue(loopRangeCall) { +class ArrayIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInArrayIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) - override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = + override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = InArrayIndicesGenerator(codegen, operatorReference, rangeCall) } -class CollectionIndicesRangeValue(loopRangeCall: ResolvedCall): CallIntrinsicRangeValue(loopRangeCall) { +class CollectionIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInCollectionIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) - override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = + override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = InCollectionIndicesGenerator(codegen, operatorReference, rangeCall) } -class CharSequenceIndicesRangeValue(loopRangeCall: ResolvedCall): CallIntrinsicRangeValue(loopRangeCall) { +class CharSequenceIndicesRangeValue(rangeCall: ResolvedCall): PrimitiveNumberRangeIntrinsicRangeValue(rangeCall) { override fun createForLoopGenerator(codegen: ExpressionCodegen, forExpression: KtForExpression) = ForInCharSequenceIndicesRangeLoopGenerator(codegen, forExpression, rangeCall) - override fun createInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = + override fun createIntrinsicInExpressionGenerator(codegen: ExpressionCodegen, operatorReference: KtSimpleNameExpression): InExpressionGenerator = InCharSequenceIndicesGenerator(codegen, operatorReference, rangeCall) } - diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt index 40620744c99..1b739f1071d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/range/RangeValues.kt @@ -41,9 +41,9 @@ fun ExpressionCodegen.createRangeValueForExpression(rangeExpression: KtExpressio return when { asmRangeType.sort == Type.ARRAY -> ArrayRangeValue() - isRange(rangeType) -> + isPrimitiveRange(rangeType) -> PrimitiveRangeRangeValue() - isProgression(rangeType) -> + isPrimitiveProgression(rangeType) -> PrimitiveProgressionRangeValue() isSubtypeOfCharSequence(rangeType, state.module.builtIns) -> CharSequenceRangeValue()