From e67a78abaf67e8354803460f6e3a5f2c91b53e05 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Wed, 1 Sep 2021 20:43:24 +0500 Subject: [PATCH] [K/N][codegen] Fix for https://youtrack.jetbrains.com/issue/KT-48543 Sometimes an interface contains final methods, they shouldn't be in its itable cause they can't be called virtually --- .../konan/descriptors/ClassLayoutBuilder.kt | 8 ++++-- .../backend.native/tests/build.gradle | 4 +++ .../interfaceCallsNCasts/finalMethod.kt | 28 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/finalMethod.kt diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt index 902cdb32904..cab0bfa2f41 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt @@ -49,7 +49,6 @@ internal class OverriddenFunctionInfo( && function.bridgeDirectionsTo(overriddenFunction).allNotNeeded() fun getImplementation(context: Context): IrSimpleFunction? { - val target = function.target val implementation = if (!needBridge) target @@ -351,8 +350,11 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va val interfaceVTableEntries: List by lazy { require(irClass.isInterface) - irClass.overridableOrOverridingMethods - .filter { f -> f.isReal || f.overriddenSymbols.any { f.needBridgeTo(it.owner) } } + irClass.simpleFunctions() + .filter { f -> + f.isOverridable && f.bridgeTarget == null + && (f.isReal || f.overriddenSymbols.any { f.needBridgeTo(it.owner) }) + } .sortedBy { it.uniqueName } } diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index ecdd40ed7b4..9cb6caa17e1 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -2971,6 +2971,10 @@ task interfaceCallsNCasts_functionNameClash(type: KonanLocalTest) { source = "codegen/interfaceCallsNCasts/functionNameClash.kt" } +task interfaceCallsNCasts_finalMethod(type: KonanLocalTest) { + source = "codegen/interfaceCallsNCasts/finalMethod.kt" +} + task interfaceCallsNCasts_diamond(type: KonanLocalTest) { source = "codegen/interfaceCallsNCasts/diamond.kt" } diff --git a/kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/finalMethod.kt b/kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/finalMethod.kt new file mode 100644 index 00000000000..a47cac60a9f --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/interfaceCallsNCasts/finalMethod.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.interfaceCallsNCasts.finalMethod + +import kotlin.test.* + +interface I1 { + fun defaultX(): T + fun foo(x: T = defaultX()): T +} + +interface I2 : I1 { + +} + +class C : I2 { + override fun defaultX() = 42 + override fun foo(x: Int) = x +} + +@Test +fun runTest() { + val c: I2 = C() + assertEquals(42, c.foo()) +} \ No newline at end of file