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 6b741a67337..4885061fec9 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 @@ -131,27 +131,29 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen origin: IrStatementOrigin, ktLeft: KtExpression, resolvedCall: ResolvedCall<*> - ): AssignmentReceiver { - if (isValInitializationInConstructor(descriptor, resolvedCall)) { - val thisClass = getThisClass() - val irThis = IrGetValueImpl(ktLeft.startOffset, ktLeft.endOffset, thisClass.thisAsReceiverParameter) - return BackingFieldLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, - RematerializableValue(irThis), null) - } + ): AssignmentReceiver = + if (isValInitializationInConstructor(descriptor, resolvedCall)) { + val thisClass = getThisClass() + val irThis = IrGetValueImpl(ktLeft.startOffset, ktLeft.endOffset, thisClass.thisAsReceiverParameter) - val propertyReceiver = statementGenerator.generateCallReceiver( - ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, - isSafe = resolvedCall.call.isSafeCall(), - isAssignmentReceiver = true) + BackingFieldLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, + RematerializableValue(irThis), null) + } + else { + val propertyReceiver = statementGenerator.generateCallReceiver( + ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, + isSafe = resolvedCall.call.isSafeCall(), + isAssignmentReceiver = true) - val superQualifier = getSuperQualifier(resolvedCall) + val superQualifier = getSuperQualifier(resolvedCall) - return SimplePropertyLValue(context, scope, ktLeft.startOffset, ktLeft.endOffset, origin, descriptor, - getTypeArguments(resolvedCall), propertyReceiver, superQualifier) - } + SimplePropertyLValue(context, scope, ktLeft.startOffset, ktLeft.endOffset, origin, descriptor, + getTypeArguments(resolvedCall), propertyReceiver, superQualifier) + } private fun isValInitializationInConstructor(descriptor: PropertyDescriptor, resolvedCall: ResolvedCall<*>): Boolean = !descriptor.isVar && + descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && statementGenerator.scopeOwner.let { it is ConstructorDescriptor || it is ClassDescriptor } && resolvedCall.dispatchReceiver is ThisClassReceiver diff --git a/compiler/testData/ir/irText/expressions/kt16904.kt b/compiler/testData/ir/irText/expressions/kt16904.kt new file mode 100644 index 00000000000..8039463c9f5 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/kt16904.kt @@ -0,0 +1,30 @@ +// FILE: J.java + +public class J { + public int field = 0; +} + +// FILE: kt16904.kt + +abstract class A { + val x = B() + var y = 0 +} + +class B { + operator fun plusAssign(x: Int) { + } +} + +class Test1 : A { + constructor() { + x += 42 + y += 42 + } +} + +class Test2 : J() { + init { + field = 42 + } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/kt16904.txt b/compiler/testData/ir/irText/expressions/kt16904.txt new file mode 100644 index 00000000000..879594cb6f6 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/kt16904.txt @@ -0,0 +1,67 @@ +FILE /kt16904.kt + CLASS CLASS A + CONSTRUCTOR public constructor A() + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='A' + PROPERTY public final val x: B + FIELD PROPERTY_BACKING_FIELD public final val x: B + EXPRESSION_BODY + CALL 'constructor B()' type=B origin=null + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): B + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): B' + GET_FIELD 'x: B' type=B origin=null + receiver: GET_VAR '' type=A origin=null + PROPERTY public final var y: kotlin.Int + FIELD PROPERTY_BACKING_FIELD public final var y: kotlin.Int + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'y: Int' type=kotlin.Int origin=null + receiver: GET_VAR '' type=A origin=null + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (: kotlin.Int): kotlin.Unit + BLOCK_BODY + SET_FIELD 'y: Int' type=kotlin.Unit origin=null + receiver: GET_VAR '' type=A origin=null + value: GET_VAR 'value-parameter : Int' type=kotlin.Int origin=null + CLASS CLASS B + CONSTRUCTOR public constructor B() + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='B' + FUN public final operator fun plusAssign(x: kotlin.Int): kotlin.Unit + BLOCK_BODY + CLASS CLASS Test1 + CONSTRUCTOR public constructor Test1() + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor A()' + INSTANCE_INITIALIZER_CALL classDescriptor='Test1' + BLOCK type=kotlin.Unit origin=PLUSEQ + VAR IR_TEMPORARY_VARIABLE val tmp0_this: Test1 + GET_VAR '' type=Test1 origin=null + CALL 'plusAssign(Int): Unit' type=kotlin.Unit origin=PLUSEQ + $this: CALL '(): B' type=B origin=PLUSEQ + $this: GET_VAR 'tmp0_this: Test1' type=Test1 origin=null + x: CONST Int type=kotlin.Int value='42' + BLOCK type=kotlin.Unit origin=PLUSEQ + VAR IR_TEMPORARY_VARIABLE val tmp1_this: Test1 + GET_VAR '' type=Test1 origin=null + CALL '(Int): Unit' type=kotlin.Unit origin=PLUSEQ + $this: GET_VAR 'tmp1_this: Test1' type=Test1 origin=null + : CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ + $this: CALL '(): Int' type=kotlin.Int origin=PLUSEQ + $this: GET_VAR 'tmp1_this: Test1' type=Test1 origin=null + other: CONST Int type=kotlin.Int value='42' + CLASS CLASS Test2 + CONSTRUCTOR public constructor Test2() + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor J()' + INSTANCE_INITIALIZER_CALL classDescriptor='Test2' + ANONYMOUS_INITIALIZER Test2 + BLOCK_BODY + SET_FIELD 'field: Int' type=kotlin.Unit origin=EQ + receiver: GET_VAR '' type=Test2 origin=null + value: CONST Int type=kotlin.Int value='42' diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 30d643f507f..959d1b6f7e2 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -602,6 +602,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("kt16904.kt") + public void testKt16904() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/kt16904.kt"); + doTest(fileName); + } + @TestMetadata("literals.kt") public void testLiterals() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/literals.kt");