diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt index b197d796ed0..14b9655eff9 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt @@ -47,22 +47,31 @@ abstract class AnnotationImplementationTransformer(val context: BackendContext, override fun visitClassNew(declaration: IrClass): IrStatement { - declaration.takeIf { declaration.isAnnotationClass }?.constructors?.singleOrNull()?.apply { - // Compatibility hack. Now, frontend generates constructor body for annotations and makes them open - // but, if one gets annotation from pre-1.6.20 klib, it would have no constructor body and would be final, - // so we need to fix it - if (body == null) { - declaration.modality = Modality.OPEN - body = context.createIrBuilder(symbol) - .irBlockBody(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET) { - +irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single()) - +IrInstanceInitializerCallImpl(startOffset, endOffset, declaration.symbol, context.irBuiltIns.unitType) - } - } - } + declaration.addConstructorBodyForCompatibility() return super.visitClassNew(declaration) } + protected fun IrClass.addConstructorBodyForCompatibility() { + if (!isAnnotationClass) return + val primaryConstructor = constructors.singleOrNull() ?: return + + if (primaryConstructor.body != null) return + // Compatibility hack. Now, frontend generates constructor body for annotations and makes them open + // but, if one gets annotation from pre-1.6.20 klib, it would have no constructor body and would be final, + // so we need to fix it + modality = Modality.OPEN + primaryConstructor.body = context.createIrBuilder(symbol) + .irBlockBody(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET) { + +irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single()) + +IrInstanceInitializerCallImpl( + startOffset, + endOffset, + this@addConstructorBodyForCompatibility.symbol, + context.irBuiltIns.unitType + ) + } + } + abstract fun chooseConstructor(implClass: IrClass, expression: IrConstructorCall) : IrConstructor override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt index 91bef27c07c..8af91d65b2e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsAnnotationImplementationLowering.kt @@ -40,10 +40,12 @@ class JsAnnotationImplementationTransformer(val jsContext: JsIrBackendContext) : compilationException("Should not be called", implClass) override fun visitClassNew(declaration: IrClass): IrStatement { - if (declaration.isAnnotationClass) { - implementGeneratedFunctions(declaration, declaration) + return declaration.apply { + if (isAnnotationClass) { + implementGeneratedFunctions(this, this) + } + addConstructorBodyForCompatibility() } - return super.visitClassNew(declaration) } private val arraysContentEquals: Map = diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java index 191ac1a8b3c..1816180f0de 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java @@ -39,6 +39,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { public void testAnnotationClass() throws Exception { runTest("js/js.translator/testData/box/annotation/annotationClass.kt"); } + + @Test + @TestMetadata("multipleEqualMethodsBug.kt") + public void testMultipleEqualMethodsBug() throws Exception { + runTest("js/js.translator/testData/box/annotation/multipleEqualMethodsBug.kt"); + } } @Nested diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java index fe2f0bef9aa..abe8e000f51 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java @@ -39,6 +39,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest { public void testAnnotationClass() throws Exception { runTest("js/js.translator/testData/box/annotation/annotationClass.kt"); } + + @Test + @TestMetadata("multipleEqualMethodsBug.kt") + public void testMultipleEqualMethodsBug() throws Exception { + runTest("js/js.translator/testData/box/annotation/multipleEqualMethodsBug.kt"); + } } @Nested diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index fa2bda92a4a..59f595b5d78 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -39,6 +39,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { public void testAnnotationClass() throws Exception { runTest("js/js.translator/testData/box/annotation/annotationClass.kt"); } + + @Test + @TestMetadata("multipleEqualMethodsBug.kt") + public void testMultipleEqualMethodsBug() throws Exception { + runTest("js/js.translator/testData/box/annotation/multipleEqualMethodsBug.kt"); + } } @Nested diff --git a/js/js.translator/testData/box/annotation/multipleEqualMethodsBug.kt b/js/js.translator/testData/box/annotation/multipleEqualMethodsBug.kt new file mode 100644 index 00000000000..e9258d6592e --- /dev/null +++ b/js/js.translator/testData/box/annotation/multipleEqualMethodsBug.kt @@ -0,0 +1,11 @@ +// IGNORE_BACKEND: JS +// EXPECTED_REACHABLE_NODES: 1280 +package foo + +annotation class Parent { + annotation class Child +} + +fun box(): String { + return if (Parent.Child() == Parent.Child()) "OK" else "FAIL" +}