From 51c83e5f62bb2d2000d9c4a5c53947d43661415d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 16 Mar 2020 16:26:15 +0300 Subject: [PATCH] [FIR2IR] Move delegating constructor call to body start --- .../generators/ClassMemberGenerator.kt | 31 ++++++++++--------- .../box/secondaryConstructors/withReturn.kt | 1 - .../secondaryConstructors/withReturnUnit.kt | 1 - ...rderingInDelegatingConstructorCall.fir.txt | 2 +- .../classes/enumWithMultipleCtors.fir.txt | 18 +++++------ .../ir/irText/classes/initVar.fir.txt | 4 +-- ...mplicitCastInReturnFromConstructor.fir.txt | 2 +- .../ir/irText/expressions/kt16904.fir.txt | 4 +-- .../thisReferenceBeforeClassDeclared.fir.txt | 2 +- 9 files changed, 32 insertions(+), 33 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index 98346172d36..fd0849550c6 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -94,31 +94,28 @@ internal class ClassMemberGenerator( valueParameter.setDefaultValue(firValueParameter) } } - var body = firFunction?.body?.let { visitor.convertToIrBlockBody(it) } if (firFunction is FirConstructor && irFunction is IrConstructor && !parentAsClass.isAnnotationClass) { - if (body == null) { - body = IrBlockBodyImpl(startOffset, endOffset) - } + val body = IrBlockBodyImpl(startOffset, endOffset) val delegatedConstructor = firFunction.delegatedConstructor if (delegatedConstructor != null) { val irDelegatingConstructorCall = delegatedConstructor.toIrDelegatingConstructorCall() - body.statements += irDelegatingConstructorCall ?: delegatedConstructor.convertWithOffsets { startOffset, endOffset -> - IrErrorCallExpressionImpl( - startOffset, endOffset, returnType, "Cannot find delegated constructor call" - ) - } + body.statements += irDelegatingConstructorCall } if (delegatedConstructor?.isThis == false) { - val irClass = parent as IrClass - body.statements += IrInstanceInitializerCallImpl( - startOffset, endOffset, irClass.symbol, irFunction.constructedClassType + val instanceInitializerCall = IrInstanceInitializerCallImpl( + startOffset, endOffset, (parent as IrClass).symbol, irFunction.constructedClassType ) + body.statements += instanceInitializerCall + } + val regularBody = firFunction.body?.let { visitor.convertToIrBlockBody(it) } + if (regularBody != null) { + body.statements += regularBody.statements } if (body.statements.isNotEmpty()) { irFunction.body = body } } else if (irFunction !is IrConstructor) { - irFunction.body = body + irFunction.body = firFunction?.body?.let { visitor.convertToIrBlockBody(it) } } if (irFunction !is IrConstructor || !irFunction.isPrimary) { // Scope for primary constructor should be left after class declaration @@ -247,10 +244,14 @@ internal class ClassMemberGenerator( return this } - private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrCallWithIndexedArgumentsBase? { + private fun FirDelegatedConstructorCall.toIrDelegatingConstructorCall(): IrExpressionBase { val constructedIrType = constructedTypeRef.toIrType() val constructorSymbol = (this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol - ?: return null + ?: return convertWithOffsets { startOffset, endOffset -> + IrErrorCallExpressionImpl( + startOffset, endOffset, constructedIrType, "Cannot find delegated constructor call" + ) + } return convertWithOffsets { startOffset, endOffset -> val irConstructorSymbol = declarationStorage.getIrFunctionSymbol(constructorSymbol) as IrConstructorSymbol if (constructorSymbol.fir.isFromEnumClass || constructorSymbol.fir.returnTypeRef.isEnum) { diff --git a/compiler/testData/codegen/box/secondaryConstructors/withReturn.kt b/compiler/testData/codegen/box/secondaryConstructors/withReturn.kt index 2864a07f950..b6cb18cf2af 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/withReturn.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/withReturn.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class A { val prop: Int constructor(arg: Boolean) { diff --git a/compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt b/compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt index 1fae47c1eed..956c6db367e 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR class A { val prop: Int constructor(arg: Boolean) { diff --git a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt index fa85d0abd1e..58fd3eab1b9 100644 --- a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt +++ b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.fir.txt @@ -83,7 +83,7 @@ FILE fqName: fileName:/argumentReorderingInDelegatingConstructorCall.kt VALUE_PARAMETER name:xx index:0 type:kotlin.Int VALUE_PARAMETER name:yy index:1 type:kotlin.Int BLOCK_BODY - ERROR_CALL 'Cannot find delegated constructor call' type=.Test2 + ERROR_CALL 'Cannot find delegated constructor call' type=kotlin.Any INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test2 modality:FINAL visibility:public superTypes:[.Base]' CONSTRUCTOR visibility:public <> (xxx:kotlin.Int, yyy:kotlin.Int, a:kotlin.Any) returnType:.Test2 VALUE_PARAMETER name:xxx index:0 type:kotlin.Int diff --git a/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.txt b/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.txt index 1146b5fade8..5da8c44b81e 100644 --- a/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.txt +++ b/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.txt @@ -80,32 +80,32 @@ FILE fqName: fileName:/enumWithMultipleCtors.kt CONSTRUCTOR visibility:private <> (arg:kotlin.String) returnType:.A VALUE_PARAMETER name:arg index:0 type:kotlin.String BLOCK_BODY - SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:prop1 type:kotlin.String visibility:private [final]' type=kotlin.Unit origin=null - receiver: GET_VAR ': .A declared in .A' type=.A origin=null - value: GET_VAR 'arg: kotlin.String declared in .A.' type=kotlin.String origin=null ENUM_CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum' : .A INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Enum<.A>]' + SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:prop1 type:kotlin.String visibility:private [final]' type=kotlin.Unit origin=null + receiver: GET_VAR ': .A declared in .A' type=.A origin=null + value: GET_VAR 'arg: kotlin.String declared in .A.' type=kotlin.String origin=null CONSTRUCTOR visibility:private <> () returnType:.A BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum' + : .A + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Enum<.A>]' SET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:prop1 type:kotlin.String visibility:private [final]' type=kotlin.Unit origin=null receiver: GET_VAR ': .A declared in .A' type=.A origin=null value: CONST String type=kotlin.String value="default" CALL 'public final fun (: kotlin.String): kotlin.Unit declared in .A' type=kotlin.Unit origin=EQ $this: GET_VAR ': .A declared in .A' type=.A origin=null : CONST String type=kotlin.String value="empty" - ENUM_CONSTRUCTOR_CALL 'public constructor (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum' - : .A - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Enum<.A>]' CONSTRUCTOR visibility:private <> (x:kotlin.Int) returnType:.A VALUE_PARAMETER name:x index:0 type:kotlin.Int BLOCK_BODY - CALL 'public final fun (: kotlin.String): kotlin.Unit declared in .A' type=kotlin.Unit origin=EQ - $this: GET_VAR ': .A declared in .A' type=.A origin=null - : CONST String type=kotlin.String value="int" ENUM_CONSTRUCTOR_CALL 'private constructor (arg: kotlin.String) declared in .A' arg: CALL 'public open fun toString (): kotlin.String declared in kotlin.Any' type=kotlin.String origin=null $this: GET_VAR 'x: kotlin.Int declared in .A.' type=kotlin.Int origin=null + CALL 'public final fun (: kotlin.String): kotlin.Unit declared in .A' type=kotlin.Unit origin=EQ + $this: GET_VAR ': .A declared in .A' type=.A origin=null + : CONST String type=kotlin.String value="int" FUN name:f visibility:public modality:OPEN <> ($this:.A) returnType:kotlin.String $this: VALUE_PARAMETER name: type:.A BLOCK_BODY diff --git a/compiler/testData/ir/irText/classes/initVar.fir.txt b/compiler/testData/ir/irText/classes/initVar.fir.txt index 72886acb0fa..caf8fc507f7 100644 --- a/compiler/testData/ir/irText/classes/initVar.fir.txt +++ b/compiler/testData/ir/irText/classes/initVar.fir.txt @@ -214,11 +214,11 @@ FILE fqName: fileName:/initVar.kt value: GET_VAR 'value: kotlin.Int declared in .TestInitVarWithCustomSetterInCtor.' type=kotlin.Int origin=null CONSTRUCTOR visibility:public <> () returnType:.TestInitVarWithCustomSetterInCtor BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestInitVarWithCustomSetterInCtor modality:FINAL visibility:public superTypes:[kotlin.Any]' CALL 'public final fun (value: kotlin.Int): kotlin.Unit declared in .TestInitVarWithCustomSetterInCtor' type=kotlin.Unit origin=EQ $this: GET_VAR ': .TestInitVarWithCustomSetterInCtor declared in .TestInitVarWithCustomSetterInCtor' type=.TestInitVarWithCustomSetterInCtor origin=null value: CONST Int type=kotlin.Int value=42 - DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:TestInitVarWithCustomSetterInCtor modality:FINAL visibility:public superTypes:[kotlin.Any]' FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/expressions/implicitCastInReturnFromConstructor.fir.txt b/compiler/testData/ir/irText/expressions/implicitCastInReturnFromConstructor.fir.txt index d600620512e..a72a9443df0 100644 --- a/compiler/testData/ir/irText/expressions/implicitCastInReturnFromConstructor.fir.txt +++ b/compiler/testData/ir/irText/expressions/implicitCastInReturnFromConstructor.fir.txt @@ -8,6 +8,7 @@ FILE fqName: fileName:/implicitCastInReturnFromConstructor.kt CONSTRUCTOR visibility:public <> (x:kotlin.Any?) returnType:.C VALUE_PARAMETER name:x index:0 type:kotlin.Any? BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .C' WHEN type=kotlin.Unit origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Unit @@ -15,7 +16,6 @@ FILE fqName: fileName:/implicitCastInReturnFromConstructor.kt then: RETURN type=kotlin.Nothing from='public constructor (x: kotlin.Any?) declared in .C' TYPE_OP type=kotlin.Unit origin=IMPLICIT_CAST typeOperand=kotlin.Unit GET_VAR 'x: kotlin.Any? declared in .C.' type=kotlin.Any? origin=null - DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .C' FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] overridden: public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any diff --git a/compiler/testData/ir/irText/expressions/kt16904.fir.txt b/compiler/testData/ir/irText/expressions/kt16904.fir.txt index 6e39f4799ef..1374fca74ff 100644 --- a/compiler/testData/ir/irText/expressions/kt16904.fir.txt +++ b/compiler/testData/ir/irText/expressions/kt16904.fir.txt @@ -75,6 +75,8 @@ FILE fqName: fileName:/kt16904.kt $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Test1 CONSTRUCTOR visibility:public <> () returnType:.Test1 BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test1 modality:FINAL visibility:public superTypes:[.A]' CALL 'public final fun plusAssign (x: kotlin.Int): kotlin.Unit [operator] declared in .B' type=kotlin.Unit origin=null $this: CALL 'public final fun (): .B declared in .A' type=.B origin=GET_PROPERTY $this: GET_VAR ': .Test1 declared in .Test1' type=.Test1 origin=null @@ -84,8 +86,6 @@ FILE fqName: fileName:/kt16904.kt $this: CALL 'public final fun (): kotlin.Int declared in .A' type=kotlin.Int origin=GET_PROPERTY $this: GET_VAR ': .Test1 declared in .Test1' type=.Test1 origin=null other: CONST Int type=kotlin.Int value=42 - DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test1 modality:FINAL visibility:public superTypes:[.A]' PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.Test1) returnType:.B [fake_override] correspondingProperty: PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] diff --git a/compiler/testData/ir/irText/expressions/thisReferenceBeforeClassDeclared.fir.txt b/compiler/testData/ir/irText/expressions/thisReferenceBeforeClassDeclared.fir.txt index 7b2f99fa530..14b6e001b64 100644 --- a/compiler/testData/ir/irText/expressions/thisReferenceBeforeClassDeclared.fir.txt +++ b/compiler/testData/ir/irText/expressions/thisReferenceBeforeClassDeclared.fir.txt @@ -8,7 +8,7 @@ FILE fqName: fileName:/thisReferenceBeforeClassDeclared.kt $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.test. CONSTRUCTOR visibility:private <> () returnType:.test. [primary] BLOCK_BODY - ERROR_CALL 'Cannot find delegated constructor call' type=.test. + ERROR_CALL 'Cannot find delegated constructor call' type=.WithCompanion INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name: modality:FINAL visibility:local superTypes:[.WithCompanion]' CONSTRUCTOR_CALL 'private constructor () [primary] declared in .test.' type=.test. origin=OBJECT_LITERAL VAR name:test2 type:.test. [val]