diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt index 2ad7bd71fa3..8d90619eceb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt @@ -69,7 +69,11 @@ object BuiltinSpecialBridgesUtil { val bridgesToGenerate = reachableDeclarations.mapTo(LinkedHashSet(), signatureByDescriptor) bridgesToGenerate.remove(overriddenBuiltinSignature) - bridgesToGenerate.remove(methodItself) + + val superImplementationDescriptor = findSuperImplementationForStubDelegation(function, fake) + if (superImplementationDescriptor != null || !fake) { + bridgesToGenerate.remove(methodItself) + } if (fake) { for (overridden in function.overriddenDescriptors.map { it.original }) { @@ -80,19 +84,25 @@ object BuiltinSpecialBridgesUtil { } val bridges: MutableSet> = - (bridgesToGenerate.map { BridgeForBuiltinSpecial(it, methodItself) } + specialBridge.singletonOrEmptyList()).toMutableSet() + (bridgesToGenerate.map { BridgeForBuiltinSpecial(it, overriddenBuiltinSignature) } + specialBridge.singletonOrEmptyList()).toMutableSet() - if (function.modality == Modality.OPEN && fake) { - val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function)).descriptor - if (!DescriptorUtils.isInterface(implementation.containingDeclaration)) { - bridges.add(BridgeForBuiltinSpecial(methodItself, signatureByDescriptor(implementation), isDelegateToSuper = true)) - } + if (superImplementationDescriptor != null) { + bridges.add(BridgeForBuiltinSpecial(methodItself, signatureByDescriptor(superImplementationDescriptor), isDelegateToSuper = true)) } return bridges } } + +private fun findSuperImplementationForStubDelegation(function: FunctionDescriptor, fake: Boolean): FunctionDescriptor? { + if (function.modality != Modality.OPEN || !fake) return null + val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function)).descriptor + if (DescriptorUtils.isInterface(implementation.containingDeclaration)) return null + + return implementation +} + private fun findAllReachableDeclarations(functionDescriptor: FunctionDescriptor): MutableSet = findAllReachableDeclarations(DescriptorBasedFunctionHandle(functionDescriptor)).map { it.descriptor }.toMutableSet() diff --git a/compiler/testData/codegen/box/builtinsProperties/enumAsOrdinaled.kt b/compiler/testData/codegen/box/builtinsProperties/enumAsOrdinaled.kt new file mode 100644 index 00000000000..6b3eda01d77 --- /dev/null +++ b/compiler/testData/codegen/box/builtinsProperties/enumAsOrdinaled.kt @@ -0,0 +1,16 @@ +interface Ordinaled { + val ordinal: Int +} + +enum class A : Ordinaled { + X +} + + +fun box(): String { + val result = (A.X as Ordinaled).ordinal + + if (result != 0) return "fail 1: $result" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/builtinFunctions/removeAt.kt b/compiler/testData/codegen/bytecodeText/builtinFunctions/removeAt.kt index d6bea2227ce..9aad3d2d0d3 100644 --- a/compiler/testData/codegen/bytecodeText/builtinFunctions/removeAt.kt +++ b/compiler/testData/codegen/bytecodeText/builtinFunctions/removeAt.kt @@ -90,27 +90,18 @@ fun box( } /* -9 public final bridge remove\(I\) -> Bridges for removeAt from A1-A10, but no in A9 (interface) -7 public synthetic bridge remove\(I\)Ljava/lang/Object; -> Synthetic bridges from A2-A7 + A10. None for A9 (interface) and A8 (inherited from ArrayList) -16 INVOKEVIRTUAL A[0-9]+.removeAt \(I\) -> calls in bridges -1 public remove\(Ljava/lang/Integer;\)Z -> implementation in A10 -3 public abstract removeAt\(I\) -> A4, A6, A7 +9 INVOKEVIRTUAL A[0-9]+.removeAt \(I\) -> calls in bridges with signature `public final bridge remove\(I\)` +16 INVOKEVIRTUAL A[0-9]+\.remove \(I\) -> calls to A1-A9.removeAt + 7 calls from `public synthetic bridge remove\(I\)Ljava/lang/Object;` 1 INVOKEINTERFACE A9\.remove \(I\) -> call A9.removeAt 1 INVOKEINTERFACE A9\.remove \(Ljava/lang/Object;\) -> call A9.remove -9 INVOKEVIRTUAL A[0-9]+\.remove \(I\) -> calls to A1-A9.removeAt +2 INVOKEVIRTUAL A10\.remove \(I\) -> one call in function and one from `public synthetic bridge remove(I)Ljava/lang/Object;` bridge in A10 */ -// 9 public final bridge remove\(I\) -// 7 public synthetic bridge remove\(I\)Ljava/lang/Object; -// 1 public remove\(Ljava/lang/Integer;\)Z -// 3 public abstract removeAt\(I\) -// 16 INVOKEVIRTUAL A[0-9]+.removeAt \(I\) +// 9 INVOKEVIRTUAL A[0-9]+.removeAt \(I\) +// 16 INVOKEVIRTUAL A[0-9]+\.remove \(I\) // 1 INVOKEINTERFACE A9\.remove \(I\) // 1 INVOKEINTERFACE A9\.remove \(Ljava/lang/Object;\) -// 9 INVOKEVIRTUAL A[0-9]+\.remove \(I\) -// 1 INVOKEVIRTUAL A10\.remove \(I\) -// 9 INVOKEVIRTUAL A[0-9]+\.remove \(I\) -// 1 INVOKEVIRTUAL A10\.remove \(I\) +// 2 INVOKEVIRTUAL A10\.remove \(I\) // 2 INVOKEINTERFACE java\/util\/List.remove \(I\) // 2 INVOKEINTERFACE java\/util\/List.remove \(Ljava/lang/Object;\) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index ca0fb7791db..0a7f761608a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -910,6 +910,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("enumAsOrdinaled.kt") + public void testEnumAsOrdinaled() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinsProperties/enumAsOrdinaled.kt"); + doTest(fileName); + } + @TestMetadata("explicitSuperCall.kt") public void testExplicitSuperCall() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/builtinsProperties/explicitSuperCall.kt");