diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt index 4fabcaace8e..9aaff7b30c8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InteropLowering.kt @@ -186,7 +186,7 @@ private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfor it is IrProperty && it.annotations.hasAnnotation(interop.objCOutlet.fqNameSafe) -> generateOutletSetterImp(it) - it is IrConstructor && it.annotations.hasAnnotation(interop.objCOverrideInit.fqNameSafe) -> + it is IrConstructor && it.isOverrideInit() -> generateOverrideInit(irClass, it) else -> null @@ -199,6 +199,17 @@ private class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfor } } + private fun IrConstructor.isOverrideInit(): Boolean { + if (this.origin != IrDeclarationOrigin.DEFINED) { + // Make best efforts to skip generated stubs that might have got annotations + // copied from original declarations. + // For example, default argument stubs (https://youtrack.jetbrains.com/issue/KT-41910). + return false + } + + return this.annotations.hasAnnotation(context.interopBuiltIns.objCOverrideInit.fqNameSafe) + } + private fun generateOverrideInit(irClass: IrClass, constructor: IrConstructor): IrSimpleFunction { val superClass = irClass.getSuperClassNotAny()!! val superConstructors = superClass.constructors.filter { diff --git a/backend.native/tests/interop/objc/tests/overrideInit.kt b/backend.native/tests/interop/objc/tests/overrideInit.kt index 2631e6659ca..d251cb0f387 100644 --- a/backend.native/tests/interop/objc/tests/overrideInit.kt +++ b/backend.native/tests/interop/objc/tests/overrideInit.kt @@ -2,10 +2,21 @@ import kotlinx.cinterop.* import kotlin.test.* import objcTests.* -@Test fun testOverrideInit() { - assertEquals(42, (TestOverrideInitImpl.createWithValue(42) as TestOverrideInitImpl).value) +@Test fun testOverrideInit1() { + assertEquals(42, (TestOverrideInitImpl1.createWithValue(42) as TestOverrideInitImpl1).value) } -private class TestOverrideInitImpl @OverrideInit constructor(val value: Int) : TestOverrideInit(value) { +private class TestOverrideInitImpl1 @OverrideInit constructor(val value: Int) : TestOverrideInit(value) { + companion object : TestOverrideInitMeta() +} + +// See https://youtrack.jetbrains.com/issue/KT-41910 +@Test fun testOverrideInitWithDefaultArguments() { + assertEquals(42, (TestOverrideInitImpl2.createWithValue(42) as TestOverrideInitImpl2).value) + assertEquals(123, TestOverrideInitImpl2(123).value) + assertEquals(17, TestOverrideInitImpl2().value) +} + +private class TestOverrideInitImpl2 @OverrideInit constructor(val value: Int = 17) : TestOverrideInit(value) { companion object : TestOverrideInitMeta() }