diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt index 6ddf96d6176..177779dcddf 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi2ir.generators.CallGenerator import org.jetbrains.kotlin.psi2ir.generators.pregenerateValueArgumentsUsing import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.types.KotlinType class ArrayAccessAssignmentReceiver( @@ -42,32 +43,59 @@ class ArrayAccessAssignmentReceiver( private val origin: IrStatementOrigin ) : AssignmentReceiver { + private val indexedGetDescriptor = indexedGetResolvedCall?.resultingDescriptor + private val indexedSetDescriptor = indexedSetResolvedCall?.resultingDescriptor + private val descriptor = - indexedGetResolvedCall?.resultingDescriptor - ?: indexedSetResolvedCall?.resultingDescriptor + indexedGetDescriptor + ?: indexedSetDescriptor ?: throw AssertionError("Array access should have either indexed-get call or indexed-set call") override fun assign(withLValue: (LValue) -> IrExpression): IrExpression { val kotlinType: KotlinType = - indexedGetResolvedCall?.run { resultingDescriptor.returnType!! } - ?: indexedSetResolvedCall?.run { resultingDescriptor.valueParameters.last().type } + indexedGetDescriptor?.returnType + ?: indexedSetDescriptor?.run { valueParameters.last().type } ?: throw AssertionError("Array access should have either indexed-get call or indexed-set call") val hasResult = origin.isAssignmentOperatorWithResult() val resultType = if (hasResult) kotlinType else callGenerator.context.builtIns.unitType val irResultType = callGenerator.translateType(resultType) + + if (indexedGetDescriptor?.isDynamic() != false && indexedSetDescriptor?.isDynamic() != false) { + return withLValue( + createLValue(kotlinType, OnceExpressionValue(irArray)) { _, irIndex -> + OnceExpressionValue(irIndex) + } + ) + } + val irBlock = IrBlockImpl(startOffset, endOffset, irResultType, origin) val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irArray, irBlock, "array") - val ktExpressionToIrIndexValue = HashMap() + irBlock.inlineStatement( + withLValue( + createLValue(kotlinType, irArrayValue) { i, irIndex -> + callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irIndex, irBlock, "index$i") + } + ) + ) + return irBlock + } + + private fun createLValue( + kotlinType: KotlinType, + irArrayValue: IntermediateValue, + createIndexValue: (Int, IrExpression) -> IntermediateValue + ): LValueWithGetterAndSetterCalls { + val ktExpressionToIrIndexValue = HashMap() for ((i, irIndex) in irIndexExpressions.withIndex()) { ktExpressionToIrIndexValue[ktIndexExpressions[i]] = - callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irIndex, irBlock, "index$i") + createIndexValue(i, irIndex) } - val irLValue = LValueWithGetterAndSetterCalls( + return LValueWithGetterAndSetterCalls( callGenerator, descriptor, { indexedGetCall()?.fillArrayAndIndexArguments(irArrayValue, indexedGetResolvedCall!!, ktExpressionToIrIndexValue) }, @@ -75,9 +103,6 @@ class ArrayAccessAssignmentReceiver( callGenerator.translateType(kotlinType), startOffset, endOffset, origin ) - irBlock.inlineStatement(withLValue(irLValue)) - - return irBlock } override fun assign(value: IrExpression): IrExpression { diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicArrayAugmentedAssignment.txt b/compiler/testData/ir/irJsText/dynamic/dynamicArrayAugmentedAssignment.txt index e07981b25b8..db041edefb5 100644 --- a/compiler/testData/ir/irJsText/dynamic/dynamicArrayAugmentedAssignment.txt +++ b/compiler/testData/ir/irJsText/dynamic/dynamicArrayAugmentedAssignment.txt @@ -2,53 +2,28 @@ FILE fqName: fileName:/dynamicArrayAugmentedAssignment.kt FUN name:testArrayAugmentedAssignment visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Unit flags: VALUE_PARAMETER name:d index:0 type:dynamic flags: BLOCK_BODY - BLOCK type=kotlin.Unit origin=PLUSEQ - VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="KEY" - DYN_OP operator=PLUSEQ type=kotlin.Unit - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp0_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp1_index0: String' type=kotlin.String origin=null - 0: CONST String type=kotlin.String value="+=" - BLOCK type=kotlin.Unit origin=MINUSEQ - VAR IR_TEMPORARY_VARIABLE name:tmp2_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp3_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="KEY" - DYN_OP operator=MINUSEQ type=kotlin.Unit - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp2_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp3_index0: String' type=kotlin.String origin=null - 0: CONST String type=kotlin.String value="-=" - BLOCK type=kotlin.Unit origin=MULTEQ - VAR IR_TEMPORARY_VARIABLE name:tmp4_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp5_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="KEY" - DYN_OP operator=MULEQ type=kotlin.Unit - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp4_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp5_index0: String' type=kotlin.String origin=null - 0: CONST String type=kotlin.String value="*=" - BLOCK type=kotlin.Unit origin=DIVEQ - VAR IR_TEMPORARY_VARIABLE name:tmp6_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp7_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="KEY" - DYN_OP operator=DIVEQ type=kotlin.Unit - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp6_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp7_index0: String' type=kotlin.String origin=null - 0: CONST String type=kotlin.String value="/=" - BLOCK type=kotlin.Unit origin=PERCEQ - VAR IR_TEMPORARY_VARIABLE name:tmp8_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp9_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="KEY" - DYN_OP operator=MODEQ type=kotlin.Unit - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp8_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp9_index0: String' type=kotlin.String origin=null - 0: CONST String type=kotlin.String value="%=" + DYN_OP operator=PLUSEQ type=kotlin.Unit + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="KEY" + 0: CONST String type=kotlin.String value="+=" + DYN_OP operator=MINUSEQ type=kotlin.Unit + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="KEY" + 0: CONST String type=kotlin.String value="-=" + DYN_OP operator=MULEQ type=kotlin.Unit + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="KEY" + 0: CONST String type=kotlin.String value="*=" + DYN_OP operator=DIVEQ type=kotlin.Unit + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="KEY" + 0: CONST String type=kotlin.String value="/=" + DYN_OP operator=MODEQ type=kotlin.Unit + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="KEY" + 0: CONST String type=kotlin.String value="%=" diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicArrayIncrementDecrement.txt b/compiler/testData/ir/irJsText/dynamic/dynamicArrayIncrementDecrement.txt index 6d38fc7ee5e..61d97f409d1 100644 --- a/compiler/testData/ir/irJsText/dynamic/dynamicArrayIncrementDecrement.txt +++ b/compiler/testData/ir/irJsText/dynamic/dynamicArrayIncrementDecrement.txt @@ -3,42 +3,22 @@ FILE fqName: fileName:/dynamicArrayIncrementDecrement.kt VALUE_PARAMETER name:d index:0 type:dynamic flags: BLOCK_BODY VAR name:t1 type:dynamic flags:val - BLOCK type=dynamic origin=PREFIX_INCR - VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="prefixIncr" - DYN_OP operator=PREFIX_INCREMENT type=dynamic - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp0_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp1_index0: String' type=kotlin.String origin=null + DYN_OP operator=PREFIX_INCREMENT type=dynamic + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="prefixIncr" VAR name:t2 type:dynamic flags:val - BLOCK type=dynamic origin=PREFIX_DECR - VAR IR_TEMPORARY_VARIABLE name:tmp2_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp3_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="prefixDecr" - DYN_OP operator=PREFIX_DECREMENT type=dynamic - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp2_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp3_index0: String' type=kotlin.String origin=null + DYN_OP operator=PREFIX_DECREMENT type=dynamic + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="prefixDecr" VAR name:t3 type:dynamic flags:val - BLOCK type=dynamic origin=POSTFIX_INCR - VAR IR_TEMPORARY_VARIABLE name:tmp4_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp5_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="postfixIncr" - DYN_OP operator=POSTFIX_INCREMENT type=dynamic - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp4_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp5_index0: String' type=kotlin.String origin=null + DYN_OP operator=POSTFIX_INCREMENT type=dynamic + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="postfixIncr" VAR name:t4 type:dynamic flags:val - BLOCK type=dynamic origin=POSTFIX_DECR - VAR IR_TEMPORARY_VARIABLE name:tmp6_array type:dynamic flags:val - GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp7_index0 type:kotlin.String flags:val - CONST String type=kotlin.String value="postfixDecr" - DYN_OP operator=POSTFIX_DECREMENT type=dynamic - receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic - receiver: GET_VAR 'tmp6_array: dynamic' type=dynamic origin=null - 0: GET_VAR 'tmp7_index0: String' type=kotlin.String origin=null + DYN_OP operator=POSTFIX_DECREMENT type=dynamic + receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic + receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST String type=kotlin.String value="postfixDecr"