From 7958a9debd32d20cb6f962586e89c3927c2526a9 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 27 Apr 2023 12:19:58 +0300 Subject: [PATCH] [FIR2IR] Correctly generate delegating constructor call for secondary constructors in enums ^KT-56927 Fxied --- .../fir/backend/generators/ClassMemberGenerator.kt | 13 ++++++++++++- .../box/enum/defaultCtor/noPrimaryConstructor.kt | 4 +--- .../secondaryConstructorWithDefaultArguments.kt | 3 +-- .../defaultCtor/secondaryConstructorWithVararg.kt | 3 +-- .../testData/codegen/box/enum/emptyConstructor.kt | 1 - compiler/testData/codegen/box/ir/enumClass2.kt | 3 +-- .../codegen/box/secondaryConstructors/enums.kt | 2 -- .../irText/classes/enumWithMultipleCtors.fir.ir.txt | 2 +- .../irText/classes/enumWithSecondaryCtor.fir.ir.txt | 6 +++--- 9 files changed, 20 insertions(+), 17 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 fa6102bf170..d600143d345 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 @@ -347,7 +347,18 @@ internal class ClassMemberGenerator( val irConstructorSymbol = declarationStorage.getIrFunctionSymbol(constructorSymbol) as IrConstructorSymbol val typeArguments = constructedTypeRef.coneType.fullyExpandedType(session).typeArguments val constructor = constructorSymbol.fir - if (constructor.isFromEnumClass || constructor.returnTypeRef.isEnum) { + /* + * We should generate enum constructor call only if it is used to create new enum entry (so it's super constructor call) + * If it is this constructor call that we are facing secondary constructor of enum, and should generate + * regular delegating constructor call + * + * enum class Some(val x: Int) { + * A(); // <---- super call, IrEnumConstructorCall + * + * constructor() : this(10) // <---- this call, IrDelegatingConstructorCall + * } + */ + if ((constructor.isFromEnumClass || constructor.returnTypeRef.isEnum) && this.isSuper) { IrEnumConstructorCallImpl( startOffset, endOffset, constructedIrType, diff --git a/compiler/testData/codegen/box/enum/defaultCtor/noPrimaryConstructor.kt b/compiler/testData/codegen/box/enum/defaultCtor/noPrimaryConstructor.kt index 2426cc0538e..14738623a80 100644 --- a/compiler/testData/codegen/box/enum/defaultCtor/noPrimaryConstructor.kt +++ b/compiler/testData/codegen/box/enum/defaultCtor/noPrimaryConstructor.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND_K2: JS_IR, NATIVE - enum class Test { A(0), B; @@ -14,4 +12,4 @@ fun box(): String = if (Test.A.n == Test.B.n) "OK" else - "Fail" \ No newline at end of file + "Fail" diff --git a/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt b/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt index 995cc739d2e..c6b40d641ef 100644 --- a/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt +++ b/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithDefaultArguments.kt @@ -1,8 +1,7 @@ -// IGNORE_BACKEND_K2: JS_IR, NATIVE enum class Test(val x: Int, val str: String) { OK; constructor(x: Int = 0) : this(x, "OK") } fun box(): String = - Test.OK.str \ No newline at end of file + Test.OK.str diff --git a/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt b/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt index 941c0ec86d9..5ac6970c940 100644 --- a/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt +++ b/compiler/testData/codegen/box/enum/defaultCtor/secondaryConstructorWithVararg.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_K2: JS_IR, NATIVE enum class Test(val x: Int, val str: String) { OK; constructor(vararg xs: Int) : this(xs.size + 42, "OK") @@ -8,4 +7,4 @@ fun box(): String = if (Test.OK.x == 42) Test.OK.str else - "Fail" \ No newline at end of file + "Fail" diff --git a/compiler/testData/codegen/box/enum/emptyConstructor.kt b/compiler/testData/codegen/box/enum/emptyConstructor.kt index 9c0040e25c6..c82a4ac41c3 100644 --- a/compiler/testData/codegen/box/enum/emptyConstructor.kt +++ b/compiler/testData/codegen/box/enum/emptyConstructor.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_K2: JS_IR, NATIVE package test enum class My(val s: String) { diff --git a/compiler/testData/codegen/box/ir/enumClass2.kt b/compiler/testData/codegen/box/ir/enumClass2.kt index 049104b55bc..5f6670fa863 100644 --- a/compiler/testData/codegen/box/ir/enumClass2.kt +++ b/compiler/testData/codegen/box/ir/enumClass2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_K2: JS_IR, NATIVE // WITH_STDLIB import kotlin.test.assertEquals @@ -16,4 +15,4 @@ fun box(): String { assertEquals(TestEnumClass.ZERO.x, 0) return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/secondaryConstructors/enums.kt b/compiler/testData/codegen/box/secondaryConstructors/enums.kt index acc6fdcdf5b..2d62a075bb9 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/enums.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/enums.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND_K2: JS_IR, NATIVE - enum class A1(val prop1: String) { X("asd"), Y() { diff --git a/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.ir.txt b/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.ir.txt index 3b330bfc82d..67fbf6466f5 100644 --- a/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.ir.txt +++ b/compiler/testData/ir/irText/classes/enumWithMultipleCtors.fir.ir.txt @@ -160,7 +160,7 @@ FILE fqName: fileName:/enumWithMultipleCtors.kt CONSTRUCTOR visibility:private <> (x:kotlin.Int) returnType:.A VALUE_PARAMETER name:x index:0 type:kotlin.Int BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'private constructor (arg: kotlin.String) declared in .A' + DELEGATING_CONSTRUCTOR_CALL 'private constructor (arg: kotlin.String) declared in .A' arg: CALL 'public final fun toString (): kotlin.String declared in kotlin.Int' 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 diff --git a/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.fir.ir.txt b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.fir.ir.txt index f9a8c0b75b4..0e85798bea2 100644 --- a/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.fir.ir.txt +++ b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.fir.ir.txt @@ -23,7 +23,7 @@ FILE fqName: fileName:/enumWithSecondaryCtor.kt ENUM_CONSTRUCTOR_CALL 'private constructor () declared in .Test0' CONSTRUCTOR visibility:private <> () returnType:.Test0 BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int) [primary] declared in .Test0' + DELEGATING_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int) [primary] declared in .Test0' x: CONST Int type=kotlin.Int value=0 FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.Test0> SYNTHETIC_BODY kind=ENUM_VALUES @@ -102,7 +102,7 @@ FILE fqName: fileName:/enumWithSecondaryCtor.kt x: CONST Int type=kotlin.Int value=1 CONSTRUCTOR visibility:private <> () returnType:.Test1 BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int) [primary] declared in .Test1' + DELEGATING_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int) [primary] declared in .Test1' x: CONST Int type=kotlin.Int value=0 FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<.Test1> SYNTHETIC_BODY kind=ENUM_VALUES @@ -303,7 +303,7 @@ FILE fqName: fileName:/enumWithSecondaryCtor.kt $this: VALUE_PARAMETER name: type:kotlin.Enum CONSTRUCTOR visibility:private <> () returnType:.Test2 BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int) [primary] declared in .Test2' + DELEGATING_CONSTRUCTOR_CALL 'private constructor (x: kotlin.Int) [primary] declared in .Test2' x: CONST Int type=kotlin.Int value=0 FUN name:foo visibility:public modality:ABSTRACT <> ($this:.Test2) returnType:kotlin.Unit $this: VALUE_PARAMETER name: type:.Test2