Call toString() within known class, during string concatenation type narrowing

^KT-53119 Improved

Merge-request: KT-MR-6755
Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
Vladimir Sukharev
2022-07-28 14:57:28 +00:00
committed by Space
parent caa1570e25
commit 412f07c55b
9 changed files with 145 additions and 3 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.shallowCopy
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
/**
* This pass replaces calls to:
@@ -134,9 +135,15 @@ internal class StringConcatenationTypeNarrowing(val context: Context) : FileLowe
private fun buildNonNullableArgToString(argument: IrExpression): IrExpression {
return if (argument.type.isString() || argument.type.isNullableString())
argument
else builder
.irCall(context.ir.symbols.memberToString, context.irBuiltIns.stringType, valueArgumentsCount = 1, typeArgumentsCount = 0)
.apply { dispatchReceiver = argument }
else {
val calleeOrNull = argument.type.classOrNull?.owner?.functions?.singleOrNull {
it.name == OperatorNameConventions.TO_STRING && it.valueParameters.isEmpty()
}?.symbol
val callee = calleeOrNull ?: context.ir.symbols.memberToString // defaults to `Any.toString()`
builder
.irCall(callee, callee.owner.returnType, valueArgumentsCount = 0, typeArgumentsCount = 0)
.apply { dispatchReceiver = argument }
}
}
/**
@@ -59,6 +59,40 @@ fun maybeAnyString(maybeAny1: Any?, string: String): String {
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyFoo
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String)
// CHECK-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-NOT: Foo#toString(){}kotlin.String
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-NOT: Foo#toString(){}kotlin.String"
// CHECK-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyFoo(maybeAny: Any?, foo: Foo): String {
return "$maybeAny,$foo"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated#maybeAnyMaybeFoo
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String)
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_generated.Foo#toString(){}kotlin.String"
// CHECK-NOT: Foo#toString(){}kotlin.String"
// CHECK-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun maybeAnyMaybeFoo(maybeAny: Any?, foo: Foo?): String {
return "$maybeAny,$foo"
}
@Test
fun runTest() {
val foo = Foo(42)
@@ -68,4 +102,8 @@ fun runTest() {
println(maybeAnyMaybeString(null, null))
println(maybeAnyString(foo, "bar"))
println(maybeAnyString(null, "bar"))
println(maybeAnyFoo(foo, foo))
println(maybeAnyFoo(null, foo))
println(maybeAnyMaybeFoo(foo, foo))
println(maybeAnyMaybeFoo(foo, null))
}
@@ -4,3 +4,7 @@ Foo(bar=42),bar
null,null
Foo(bar=42),bar
null,bar
Foo(bar=42),Foo(bar=42)
null,Foo(bar=42)
Foo(bar=42),Foo(bar=42)
Foo(bar=42),null
@@ -67,6 +67,21 @@ fun appendString(str: String): String {
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual#appendFoo(codegen.stringConcatenationTypeNarrowing.kt53119_append_manual.Foo)
// CHECK: %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_append_manual.Foo#toString(){}kotlin.String"
// CHECK-NOT: Foo#toString(){}kotlin.String"
// CHECK: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append(kotlin.String?)
// CHECK-NOT: Foo#toString(){}kotlin.String"
// CHECK-NOT: %struct.ObjHeader* @"kfun:kotlin.text.StringBuilder#append
// CHECK: ret %struct.ObjHeader*
fun appendFoo(foo: Foo): String {
val sb = kotlin.text.StringBuilder()
sb.append(foo)
return sb.toString()
}
@Test
fun runTest() {
val foo = Foo(42)
@@ -76,4 +91,5 @@ fun runTest() {
println(appendMaybeString("foo"))
println(appendMaybeString(null))
println(appendString("foo"))
println(appendFoo(foo))
}
@@ -4,3 +4,4 @@ Foo(bar=42)
foo
null
foo
Foo(bar=42)
@@ -77,6 +77,43 @@ fun generatedPlusExtensionString(maybeStr: String?, str: String): String {
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#generatedPlusExtensionFoo
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension.Foo#toString(){}kotlin.String"
// CHECK-NOT: Foo#toString(){}kotlin.String
// CHECK: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusExtensionFoo(maybeStr: String?, foo: Foo): String {
return "$maybeStr$foo"
}
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension#generatedPlusExtensionMaybeFoo
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-NOT: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_extension.Foo#toString(){}kotlin.String"
// CHECK-NOT: Foo#toString(){}kotlin.String
// CHECK-NOT: call %struct.ObjHeader* @"kfun:kotlin.String#toString(){}kotlin.String"
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK: ret %struct.ObjHeader*
fun generatedPlusExtensionMaybeFoo(maybeStr: String?, foo: Foo?): String {
return "$maybeStr$foo"
}
@Test
fun runTest() {
val foo = Foo(42)
@@ -88,4 +125,7 @@ fun runTest() {
println(generatedPlusExtensionAny(null, null))
println(generatedPlusExtensionString("foo", "bar"))
println(generatedPlusExtensionString(null, "bar"))
println(generatedPlusExtensionFoo(null, Foo(42)))
println(generatedPlusExtensionMaybeFoo("foo", Foo(42)))
println(generatedPlusExtensionMaybeFoo("foo", null))
}
@@ -6,3 +6,6 @@ fooFoo(bar=42)
nullnull
foobar
nullbar
nullFoo(bar=42)
fooFoo(bar=42)
foonull
@@ -68,6 +68,33 @@ fun generatedPlusMemberString(str1: String, str2: String): String {
data class Foo(val bar: Int)
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#manualPlusMemberFoo
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString(){}kotlin.String"
// CHECK-NOT Foo#toString(){}kotlin.String
// CHECK: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-NOT: Foo#toString(){}kotlin.String"
// CHECK: ret %struct.ObjHeader*
fun manualPlusMemberFoo(str1: String, foo: Foo): kotlin.String =
str1 + foo
// CHECK-LABEL: define %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member#manualPlusMemberMaybeFoo
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString(){}kotlin.String"
// CHECK-NOT Foo#toString(){}kotlin.String
// CHECK: call %struct.ObjHeader* @Kotlin_String_plusImpl
// CHECK: call %struct.ObjHeader* @"kfun:codegen.stringConcatenationTypeNarrowing.kt53119_plus_member.Foo#toString
// CHECK-NOT: kfun:kotlin.String#plus(kotlin.Any?)
// CHECK-NOT: Foo#toString(){}kotlin.String"
// CHECK: ret %struct.ObjHeader*
fun manualPlusMemberMaybeFoo(str1: String, foo: Foo?): kotlin.String =
str1 + foo
@Test
fun runTest() {
val foo = Foo(42)
@@ -77,4 +104,7 @@ fun runTest() {
println(generatedPlusMemberAny("foo", null))
println(generatedPlusMemberAny("foo", foo))
println(generatedPlusMemberString("foo", "bar"))
println(manualPlusMemberFoo("foo", Foo(42)))
println(manualPlusMemberMaybeFoo("foo", Foo(42)))
println(manualPlusMemberMaybeFoo("foo", null))
}
@@ -4,3 +4,6 @@ foobar
foonull
fooFoo(bar=42)
foobar
fooFoo(bar=42)
fooFoo(bar=42)
foonull