[JS IR] Fix clash between generic extension overloads

Type parameter constraints are used for calculating JS signature hash.

^KT-51151 Fixed
This commit is contained in:
Alexander Korepanov
2022-07-14 20:01:06 +02:00
committed by Space
parent 9f5cbea0fa
commit 0982872959
6 changed files with 181 additions and 1 deletions
@@ -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()}")
@@ -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 {
@@ -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 {
@@ -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 {
@@ -0,0 +1,42 @@
class Receiver()
class Scope() {
fun <T : String> Receiver.testOverload(e: T) = "String"
fun <T : CharSequence> Receiver.testOverload(e: T) = "CharSequence"
fun <T : Any> Receiver.testOverload(e: T) = "Any"
}
class NullableScope() {
fun <T : String?> Receiver.testOverload(e: T) = "String?"
fun <T : String> Receiver.testOverload(e: T) = "String"
fun <T : CharSequence> Receiver.testOverload(e: T) = "CharSequence"
fun <T : Any?> 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"
}
@@ -0,0 +1,96 @@
class Receiver()
open class A1
open class A2: A1()
open class A3: A2()
class GenericScope<E : A1>() {
class GenericSubScope<E : A2> {
fun <T : E> Receiver.testOverload(e: T) = "SubScope"
}
fun <T : E> Receiver.testOverload(e: T) = "Scope"
}
class GenericScopeWithOverloads<E : A1>() {
class GenericSubScopeWithOverloads<E : A2> {
fun <T : E> Receiver.testOverload(e: T) = "SubScope"
fun <T : A3> Receiver.testOverload(e: T) = "SubScope A3"
}
fun <T : E> Receiver.testOverload(e: T) = "Scope"
fun <T : A2> Receiver.testOverload(e: T) = "Scope A2"
fun <T : A3> Receiver.testOverload(e: T) = "Scope A3"
}
val r = Receiver()
fun testGenericScope() {
GenericScope<A1>().apply {
assertEquals("Scope", r.testOverload(A1()))
assertEquals("Scope", r.testOverload(A2()))
assertEquals("Scope", r.testOverload(A3()))
GenericScope.GenericSubScope<A2>().apply {
assertEquals("Scope", r.testOverload(A1()))
assertEquals("SubScope", r.testOverload(A2()))
assertEquals("SubScope", r.testOverload(A3()))
}
GenericScope.GenericSubScope<A3>().apply {
assertEquals("Scope", r.testOverload(A1()))
assertEquals("Scope", r.testOverload(A2()))
assertEquals("SubScope", r.testOverload(A3()))
}
}
GenericScope<A2>().apply {
assertEquals("Scope", r.testOverload(A2()))
assertEquals("Scope", r.testOverload(A3()))
GenericScope.GenericSubScope<A2>().apply {
assertEquals("SubScope", r.testOverload(A2()))
assertEquals("SubScope", r.testOverload(A3()))
}
GenericScope.GenericSubScope<A3>().apply {
assertEquals("Scope", r.testOverload(A2()))
assertEquals("SubScope", r.testOverload(A3()))
}
}
}
fun testGenericScopeWithOverloads() {
GenericScopeWithOverloads<A1>().apply {
assertEquals("Scope", r.testOverload(A1()))
assertEquals("Scope A2", r.testOverload(A2()))
assertEquals("Scope A3", r.testOverload(A3()))
GenericScopeWithOverloads.GenericSubScopeWithOverloads<A2>().apply {
assertEquals("Scope", r.testOverload(A1()))
assertEquals("SubScope", r.testOverload(A2()))
assertEquals("SubScope A3", r.testOverload(A3()))
}
GenericScopeWithOverloads.GenericSubScopeWithOverloads<A3>().apply {
assertEquals("Scope", r.testOverload(A1()))
assertEquals("Scope A2", r.testOverload(A2()))
}
}
GenericScopeWithOverloads<A2>().apply {
assertEquals("Scope A3", r.testOverload(A3()))
GenericScopeWithOverloads.GenericSubScopeWithOverloads<A2>().apply {
assertEquals("SubScope", r.testOverload(A2()))
assertEquals("SubScope A3", r.testOverload(A3()))
}
}
}
fun box(): String {
testGenericScope()
testGenericScopeWithOverloads()
return "OK"
}