diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index 79baf0d999c..233505d1b56 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -20,8 +20,8 @@ import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters import org.jetbrains.kotlin.backend.jvm.ir.isJvmAbstract import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass import org.jetbrains.kotlin.codegen.AsmUtil -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.addFunction @@ -261,11 +261,17 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass methodInfo = specialBridge.methodInfo?.copy(argumentsToCheck = 0), // For potential argument boxing isFinal = false, ) - // The part after ?: is needed for methods with default implementations in collection interfaces: + // The part after '?:' is needed for methods with default implementations in collection interfaces: // MutableMap.remove() and getOrDefault(). val superTarget = overriddenFromClass.takeIf { !it.isFakeOverride } ?: specialBridge.overridden - irClass.declarations.remove(irFunction) - irClass.addSpecialBridge(superBridge, superTarget) + if (superBridge.signature == superTarget.jvmMethod) { + // If the resulting bridge to a super member matches the signature of the bridge callee, + // bridge is not needed. + irFunction + } else { + irClass.declarations.remove(irFunction) + irClass.addSpecialBridge(superBridge, superTarget) + } } else -> irFunction } diff --git a/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.kt b/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.kt index 80ef3d3fb13..290b0d93a62 100644 --- a/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.kt +++ b/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR open class A1 { open val size: Int = 56 } diff --git a/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize_ir.txt b/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize_ir.txt new file mode 100644 index 00000000000..725225e35d9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/specialBridges/redundantStubForSize_ir.txt @@ -0,0 +1,29 @@ +@kotlin.Metadata +public class A1 { + // source: 'redundantStubForSize.kt' + private final field size: int + public method (): void + public method getSize(): int +} + +@kotlin.Metadata +public final class A2 { + // source: 'redundantStubForSize.kt' + public method (): void + public synthetic bridge method add(p0: java.lang.Object): boolean + public method add(p0: java.lang.String): boolean + public method addAll(p0: java.util.Collection): boolean + public method clear(): void + public method contains(@org.jetbrains.annotations.NotNull p0: java.lang.String): boolean + public bridge final method contains(p0: java.lang.Object): boolean + public method containsAll(@org.jetbrains.annotations.NotNull p0: java.util.Collection): boolean + public method isEmpty(): boolean + public @org.jetbrains.annotations.NotNull method iterator(): java.util.Iterator + public bridge final method remove(p0: java.lang.Object): boolean + public method remove(p0: java.lang.String): boolean + public method removeAll(p0: java.util.Collection): boolean + public method retainAll(p0: java.util.Collection): boolean + public bridge final method size(): int + public method toArray(): java.lang.Object[] + public method toArray(p0: java.lang.Object[]): java.lang.Object[] +}