diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index 6fc2d0abb77..db957b5410e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -43,11 +43,15 @@ import org.jetbrains.kotlin.types.KotlinType class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { - fun generateAssignment(ktExpression: KtBinaryExpression): IrExpression { - val ktLeft = ktExpression.left!! - val irRhs = ktExpression.right!!.genExpr() - val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, IrStatementOrigin.EQ) - return irAssignmentReceiver.assign(irRhs) + fun generateAssignment(ktExpression: KtBinaryExpression, origin: IrStatementOrigin): IrExpression { + return if (getResolvedCall(ktExpression) != null) { + generateAugmentedAssignment(ktExpression, origin) + } else { + val ktLeft = ktExpression.left!! + val irRhs = ktExpression.right!!.genExpr() + val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, IrStatementOrigin.EQ) + irAssignmentReceiver.assign(irRhs) + } } fun generateAugmentedAssignment(ktExpression: KtBinaryExpression, origin: IrStatementOrigin): IrExpression { @@ -55,7 +59,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, ktExpression) ?: false val ktLeft = ktExpression.left!! val ktRight = ktExpression.right!! - val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, origin) + val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, origin, isAugmentedAssignment = true) val isDynamicCall = opResolvedCall.resultingDescriptor.isDynamic() return irAssignmentReceiver.assign { irLValue -> @@ -167,7 +171,8 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen private fun generateAssignmentReceiver( ktLeft: KtExpression, origin: IrStatementOrigin, - isAssignmentStatement: Boolean = true + isAssignmentStatement: Boolean = true, + isAugmentedAssignment: Boolean = false ): AssignmentReceiver { val ktExpr = KtPsiUtil.safeDeparenthesize(ktLeft) if (ktExpr is KtArrayAccessExpression) { @@ -203,7 +208,14 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen else createVariableValue(ktExpr, descriptor, origin) is PropertyDescriptor -> - generateAssignmentReceiverForProperty(descriptor, origin, ktExpr, resolvedCall, isAssignmentStatement) + generateAssignmentReceiverForProperty( + descriptor, + origin, + ktExpr, + resolvedCall, + isAssignmentStatement, + isAugmentedAssignment + ) is FakeCallableDescriptorForObject -> OnceExpressionValue(ktExpr.genExpr()) is ValueDescriptor -> @@ -263,7 +275,8 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen origin: IrStatementOrigin, ktLeft: KtExpression, resolvedCall: ResolvedCall<*>, - isAssignmentStatement: Boolean + isAssignmentStatement: Boolean, + isAugmentedAssignment: Boolean ): AssignmentReceiver = when { descriptor.isDynamic() -> @@ -280,8 +293,8 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen isAssignmentReceiver = isAssignmentStatement ) ) - origin == IrStatementOrigin.EQ && !descriptor.isVar -> { - // An assignment to a val property can only be its initialization in the constructor. + origin == IrStatementOrigin.EQ && !descriptor.isVar && !isAugmentedAssignment -> { + // An assignment to a val property can only be its initialization in the constructor or an augmented assignment. val receiver = resolvedCall.dispatchReceiver ?: descriptor.dispatchReceiverParameter?.value createBackingFieldLValue(ktLeft, descriptor, statementGenerator.generateReceiverOrNull(ktLeft, receiver), null) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index 668f195d963..1d535b64d0e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -132,7 +132,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat return when (val irOperator = getInfixOperator(ktOperator)) { null -> throw AssertionError("Unexpected infix operator: $ktOperator") - IrStatementOrigin.EQ -> AssignmentGenerator(statementGenerator).generateAssignment(expression) + IrStatementOrigin.EQ -> AssignmentGenerator(statementGenerator).generateAssignment(expression, irOperator) in AUGMENTED_ASSIGNMENTS -> AssignmentGenerator(statementGenerator).generateAugmentedAssignment(expression, irOperator) IrStatementOrigin.ELVIS -> generateElvis(expression) in OPERATORS_DESUGARED_TO_CALLS -> generateBinaryOperatorAsCall(expression, irOperator)