[JS IR] Add an explicit toString() call for concatenating Char values
^KT-59718 Fixed
This commit is contained in:
committed by
Space Team
parent
b381752074
commit
2cb28b6be1
+15
-2
@@ -9,12 +9,15 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.overrides
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
import org.jetbrains.kotlin.utils.filterIsInstanceAnd
|
||||||
|
|
||||||
class JsStringConcatenationLowering(val context: CommonBackendContext) : FileLoweringPass {
|
class JsStringConcatenationLowering(val context: CommonBackendContext) : FileLoweringPass {
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
@@ -30,7 +33,9 @@ private class JsStringConcatenationTransformer(val context: CommonBackendContext
|
|||||||
// See KT-39891
|
// See KT-39891
|
||||||
if (this !is IrSimpleType) return false
|
if (this !is IrSimpleType) return false
|
||||||
return when (classifier.signature) {
|
return when (classifier.signature) {
|
||||||
IdSignatureValues.any, IdSignatureValues.comparable, IdSignatureValues.number, IdSignatureValues._long -> true
|
IdSignatureValues.any, IdSignatureValues.comparable, IdSignatureValues.number,
|
||||||
|
IdSignatureValues._long, IdSignatureValues._char
|
||||||
|
-> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +48,15 @@ private class JsStringConcatenationTransformer(val context: CommonBackendContext
|
|||||||
extensionReceiver = this@explicitlyConvertedToString
|
extensionReceiver = this@explicitlyConvertedToString
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
JsIrBuilder.buildCall(context.ir.symbols.memberToString).apply {
|
val anyToStringMethodSymbol = context.ir.symbols.memberToString
|
||||||
|
val toStringMethodSymbol = type.classOrNull?.let {
|
||||||
|
val toStringMethods = it.owner.declarations.filterIsInstanceAnd<IrSimpleFunction> { f ->
|
||||||
|
f.overrides(anyToStringMethodSymbol.owner)
|
||||||
|
}
|
||||||
|
toStringMethods.singleOrNull()?.symbol
|
||||||
|
} ?: anyToStringMethodSymbol
|
||||||
|
|
||||||
|
JsIrBuilder.buildCall(toStringMethodSymbol).apply {
|
||||||
dispatchReceiver = this@explicitlyConvertedToString
|
dispatchReceiver = this@explicitlyConvertedToString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+72
-16
@@ -1,42 +1,98 @@
|
|||||||
|
// KJS_WITH_FULL_RUNTIME
|
||||||
|
|
||||||
fun getC(c: Char) = c
|
fun getC(c: Char) = c
|
||||||
inline fun getCInline(c: Char) = c
|
inline fun getCInline(c: Char) = c
|
||||||
|
|
||||||
// CHECK_NEW_COUNT: function=testNonInline1 count=0
|
// CHECK_NEW_COUNT: function=testNonInlineEquals1 count=0
|
||||||
fun testNonInline1(a: Char, b: Char) : Boolean {
|
fun testNonInlineEquals1(a: Char, b: Char) : Boolean {
|
||||||
return getC(a) == getC(b)
|
return getC(a) == getC(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK_NEW_COUNT: function=testNonInline2 count=0
|
// CHECK_NEW_COUNT: function=testNonInlineEquals2 count=0
|
||||||
fun testNonInline2(a: Char, b: Char) : Boolean {
|
fun testNonInlineEquals2(a: Char, b: Char) : Boolean {
|
||||||
val a1 = getC(a)
|
val a1 = getC(a)
|
||||||
val b1 = getC(b)
|
val b1 = getC(b)
|
||||||
return a1 == b1
|
return a1 == b1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK_NEW_COUNT: function=testInline1 count=0
|
// CHECK_NEW_COUNT: function=testInlineEquals1 count=0
|
||||||
fun testInline1(a: Char, b: Char) : Boolean {
|
fun testInlineEquals1(a: Char, b: Char) : Boolean {
|
||||||
return getCInline(a) == getCInline(b)
|
return getCInline(a) == getCInline(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK_NEW_COUNT: function=testInline2 count=0
|
// CHECK_NEW_COUNT: function=testInlineEquals2 count=0
|
||||||
fun testInline2(a: Char, b: Char) : Boolean {
|
fun testInlineEquals2(a: Char, b: Char) : Boolean {
|
||||||
val a1 = getCInline(a)
|
val a1 = getCInline(a)
|
||||||
val b1 = getCInline(b)
|
val b1 = getCInline(b)
|
||||||
return a1 == b1
|
return a1 == b1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK_NEW_COUNT: function=testStringAppend1 count=0
|
||||||
|
fun testStringAppend1(s1: String, b: Char, s2: String) : Boolean {
|
||||||
|
val s = s1 + b
|
||||||
|
return s == s2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_NEW_COUNT: function=testStringAppend2 count=0
|
||||||
|
fun testStringAppend2(a: Char, s1: String, s2: String) : Boolean {
|
||||||
|
val s = a + s1
|
||||||
|
return s == s2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_NEW_COUNT: function=testStringAppendInline1 count=0
|
||||||
|
fun testStringAppendInline1(s1: String, b: Char, s2: String) : Boolean {
|
||||||
|
val s = s1 + getCInline(b)
|
||||||
|
return s == s2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_NEW_COUNT: function=testStringAppendInline2 count=0
|
||||||
|
fun testStringAppendInline2(a: Char, s1: String, s2: String) : Boolean {
|
||||||
|
val s = getCInline(a) + s1
|
||||||
|
return s == s2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_NEW_COUNT: function=testStringBuild count=0
|
||||||
|
fun testStringBuild(s1: String, b: Char, s2: String) : Boolean {
|
||||||
|
val s = "$s1 $b "
|
||||||
|
return s == s2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK_NEW_COUNT: function=testStringBuildInline count=0
|
||||||
|
fun testStringBuildInline(s1: String, b: Char, s2: String) : Boolean {
|
||||||
|
val s = "$s1 ${getCInline(b)} "
|
||||||
|
return s == s2
|
||||||
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
if (!testNonInline1('a', 'a')) {
|
if (!testNonInlineEquals1('a', 'a')) {
|
||||||
return "Fail testNonInline1"
|
return "Fail testNonInlineEquals1"
|
||||||
}
|
}
|
||||||
if (!testNonInline2('b', 'b')) {
|
if (!testNonInlineEquals2('b', 'b')) {
|
||||||
return "Fail testNonInline2"
|
return "Fail testNonInlineEquals2"
|
||||||
}
|
}
|
||||||
if (!testInline1('c', 'c')) {
|
if (!testInlineEquals1('c', 'c')) {
|
||||||
return "Fail testInline1"
|
return "Fail testInlineEquals1"
|
||||||
}
|
}
|
||||||
if (!testInline2('d', 'd')) {
|
if (!testInlineEquals2('d', 'd')) {
|
||||||
return "Fail testInline2"
|
return "Fail testInlineEquals2"
|
||||||
|
}
|
||||||
|
if (!testStringAppend1("hello", 'x', "hellox")) {
|
||||||
|
return "Fail testStringAppend1"
|
||||||
|
}
|
||||||
|
if (!testStringAppend2('x', "hello", "xhello")) {
|
||||||
|
return "Fail testStringAppend2"
|
||||||
|
}
|
||||||
|
if (!testStringAppendInline1("hello", 'x', "hellox")) {
|
||||||
|
return "Fail testStringAppendInline1"
|
||||||
|
}
|
||||||
|
if (!testStringAppendInline2('x', "hello", "xhello")) {
|
||||||
|
return "Fail testStringAppendInline2"
|
||||||
|
}
|
||||||
|
if (!testStringBuild("hello", 'x', "hello x ")) {
|
||||||
|
return "Fail testStringBuild"
|
||||||
|
}
|
||||||
|
if (!testStringBuildInline("hello", 'x', "hello x ")) {
|
||||||
|
return "Fail testStringBuildInline"
|
||||||
}
|
}
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user