From 0982872959ba4a4d666c29ab1a47edd8fc30e4ec Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Thu, 14 Jul 2022 20:01:06 +0200 Subject: [PATCH] [JS IR] Fix clash between generic extension overloads Type parameter constraints are used for calculating JS signature hash. ^KT-51151 Fixed --- .../kotlin/ir/backend/js/utils/NameTables.kt | 8 +- .../kotlin/js/test/BoxJsTestGenerated.java | 12 +++ .../kotlin/js/test/ir/FirJsTestGenerated.java | 12 +++ .../js/test/ir/IrBoxJsTestGenerated.java | 12 +++ .../overloadClassGenericExtension.kt | 42 ++++++++ ...loadClassGenericExtensionInGenericScope.kt | 96 +++++++++++++++++++ 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt create mode 100644 js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt index 26dab5eaa3c..cee1a2b0fa3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt @@ -139,7 +139,13 @@ fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext): S // TODO should we skip type parameters and use upper bound of type parameter when print type of value parameters? declaration.typeParameters.ifNotEmpty { nameBuilder.append("_\$t") - joinTo(nameBuilder, "") { "_${it.name.asString()}" } + forEach { typeParam -> + nameBuilder.append("_").append(typeParam.name.asString()) + typeParam.superTypes.ifNotEmpty { + nameBuilder.append("$") + joinTo(nameBuilder, "") { type -> type.asString() } + } + } } declaration.extensionReceiverParameter?.let { nameBuilder.append("_r$${it.type.asString()}") 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 8b97b0d4fd6..0f6b108220e 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 @@ -7344,6 +7344,18 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/nameClashes/nativeDeclarationAndLocalVar.kt"); } + @Test + @TestMetadata("overloadClassGenericExtension.kt") + public void testOverloadClassGenericExtension() throws Exception { + runTest("js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt"); + } + + @Test + @TestMetadata("overloadClassGenericExtensionInGenericScope.kt") + public void testOverloadClassGenericExtensionInGenericScope() throws Exception { + runTest("js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt"); + } + @Test @TestMetadata("overloadExtension.kt") public void testOverloadExtension() throws Exception { 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 2489667a332..8ba8296713d 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 @@ -7816,6 +7816,18 @@ public class FirJsTestGenerated extends AbstractFirJsTest { runTest("js/js.translator/testData/box/nameClashes/nativeDeclarationAndLocalVar.kt"); } + @Test + @TestMetadata("overloadClassGenericExtension.kt") + public void testOverloadClassGenericExtension() throws Exception { + runTest("js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt"); + } + + @Test + @TestMetadata("overloadClassGenericExtensionInGenericScope.kt") + public void testOverloadClassGenericExtensionInGenericScope() throws Exception { + runTest("js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt"); + } + @Test @TestMetadata("overloadExtension.kt") public void testOverloadExtension() throws Exception { 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 3908aa9dba2..d42915fa64f 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 @@ -7816,6 +7816,18 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/nameClashes/nativeDeclarationAndLocalVar.kt"); } + @Test + @TestMetadata("overloadClassGenericExtension.kt") + public void testOverloadClassGenericExtension() throws Exception { + runTest("js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt"); + } + + @Test + @TestMetadata("overloadClassGenericExtensionInGenericScope.kt") + public void testOverloadClassGenericExtensionInGenericScope() throws Exception { + runTest("js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt"); + } + @Test @TestMetadata("overloadExtension.kt") public void testOverloadExtension() throws Exception { diff --git a/js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt b/js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt new file mode 100644 index 00000000000..aaee12ab905 --- /dev/null +++ b/js/js.translator/testData/box/nameClashes/overloadClassGenericExtension.kt @@ -0,0 +1,42 @@ +class Receiver() + +class Scope() { + fun Receiver.testOverload(e: T) = "String" + fun Receiver.testOverload(e: T) = "CharSequence" + fun Receiver.testOverload(e: T) = "Any" +} + +class NullableScope() { + fun Receiver.testOverload(e: T) = "String?" + fun Receiver.testOverload(e: T) = "String" + fun Receiver.testOverload(e: T) = "CharSequence" + fun Receiver.testOverload(e: T) = "Any?" +} + +fun box(): String { + val stringVal: String = "Stirng value" + val charSequenceVal: CharSequence = "CharSequence value" + val anyVal: Any = "Any value" + + val r = Receiver() + + Scope().apply { + assertEquals("String", r.testOverload(stringVal)) + assertEquals("CharSequence", r.testOverload(charSequenceVal)) + assertEquals("Any", r.testOverload(anyVal)) + } + + val stringOrNullVal: String? = "Stirng? value" + val charSequenceOrNullVal: CharSequence? = "CharSequence? value" + val anyOrNullVal: Any? = "Any? value" + + NullableScope().apply { + assertEquals("String", r.testOverload(stringVal)) + assertEquals("String?", r.testOverload(stringOrNullVal)) + assertEquals("CharSequence", r.testOverload(charSequenceVal)) + assertEquals("Any?", r.testOverload(charSequenceOrNullVal)) + assertEquals("Any?", r.testOverload(anyVal)) + assertEquals("Any?", r.testOverload(anyOrNullVal)) + } + return "OK" +} diff --git a/js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt b/js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt new file mode 100644 index 00000000000..94ac641b8e5 --- /dev/null +++ b/js/js.translator/testData/box/nameClashes/overloadClassGenericExtensionInGenericScope.kt @@ -0,0 +1,96 @@ +class Receiver() + +open class A1 + +open class A2: A1() + +open class A3: A2() + +class GenericScope() { + class GenericSubScope { + fun Receiver.testOverload(e: T) = "SubScope" + } + fun Receiver.testOverload(e: T) = "Scope" +} + +class GenericScopeWithOverloads() { + class GenericSubScopeWithOverloads { + fun Receiver.testOverload(e: T) = "SubScope" + fun Receiver.testOverload(e: T) = "SubScope A3" + } + fun Receiver.testOverload(e: T) = "Scope" + fun Receiver.testOverload(e: T) = "Scope A2" + fun Receiver.testOverload(e: T) = "Scope A3" +} + +val r = Receiver() + +fun testGenericScope() { + GenericScope().apply { + assertEquals("Scope", r.testOverload(A1())) + assertEquals("Scope", r.testOverload(A2())) + assertEquals("Scope", r.testOverload(A3())) + + GenericScope.GenericSubScope().apply { + assertEquals("Scope", r.testOverload(A1())) + assertEquals("SubScope", r.testOverload(A2())) + assertEquals("SubScope", r.testOverload(A3())) + } + + GenericScope.GenericSubScope().apply { + assertEquals("Scope", r.testOverload(A1())) + assertEquals("Scope", r.testOverload(A2())) + assertEquals("SubScope", r.testOverload(A3())) + } + } + + GenericScope().apply { + assertEquals("Scope", r.testOverload(A2())) + assertEquals("Scope", r.testOverload(A3())) + + GenericScope.GenericSubScope().apply { + assertEquals("SubScope", r.testOverload(A2())) + assertEquals("SubScope", r.testOverload(A3())) + } + + GenericScope.GenericSubScope().apply { + assertEquals("Scope", r.testOverload(A2())) + assertEquals("SubScope", r.testOverload(A3())) + } + } +} + +fun testGenericScopeWithOverloads() { + GenericScopeWithOverloads().apply { + assertEquals("Scope", r.testOverload(A1())) + assertEquals("Scope A2", r.testOverload(A2())) + assertEquals("Scope A3", r.testOverload(A3())) + + GenericScopeWithOverloads.GenericSubScopeWithOverloads().apply { + assertEquals("Scope", r.testOverload(A1())) + assertEquals("SubScope", r.testOverload(A2())) + assertEquals("SubScope A3", r.testOverload(A3())) + } + + GenericScopeWithOverloads.GenericSubScopeWithOverloads().apply { + assertEquals("Scope", r.testOverload(A1())) + assertEquals("Scope A2", r.testOverload(A2())) + } + } + + GenericScopeWithOverloads().apply { + assertEquals("Scope A3", r.testOverload(A3())) + + GenericScopeWithOverloads.GenericSubScopeWithOverloads().apply { + assertEquals("SubScope", r.testOverload(A2())) + assertEquals("SubScope A3", r.testOverload(A3())) + } + } +} + +fun box(): String { + testGenericScope() + testGenericScopeWithOverloads() + + return "OK" +}