Properly find invoke method on default lambda inlining
In general case parameter type could differ from actual default lambda type.
E.g.: fun inlineFun(s: (Child) -> Base = { a: Base -> a as Child}),
where type of default lambda is '(Base) -> Child'.
In such case we should find somehow actual invoke method in bytecode knowing
only name, number of parameters and that's actual invoke is non-synthetic
regardless of bridge one.
#KT-21946 Fixed
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
open class Base
|
||||
|
||||
class Child(val value: String) : Base()
|
||||
|
||||
fun foo(a: Base): Child = a as Child
|
||||
|
||||
|
||||
inline fun inlineFun(s: (Child) -> Base = ::foo): Base {
|
||||
return s(Child("OK"))
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return (inlineFun() as Child).value
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
fun foo(a: Number): String = "OK"
|
||||
|
||||
inline fun inlineFun(s: (Double) -> String = ::foo): String {
|
||||
return s(1.0)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun()
|
||||
}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
|
||||
open class Base
|
||||
class Child(val value: String): Base()
|
||||
|
||||
inline fun inlineFun(s: (Child) -> Base = { a: Base -> a as Child}): Base {
|
||||
return s(Child("OK"))
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return (inlineFun() as Child).value
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
package test
|
||||
|
||||
interface Call {
|
||||
fun run(): String
|
||||
}
|
||||
|
||||
inline fun test(p: String, s: () -> Call = {
|
||||
object : Call {
|
||||
override fun run() = p
|
||||
}
|
||||
}) = s()
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return test("OK").run()
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
class Item
|
||||
|
||||
inline fun inlineFun(number: String, getItem: ((String) -> String?) = { null }): String {
|
||||
return number + (getItem(number) ?: "")
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun("OK")
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
inline fun inlineFun(action: () -> Any = { "OK" }): Any {
|
||||
return action()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun() as String
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// FILE: 1.kt
|
||||
// SKIP_INLINE_CHECK_IN: enumOrThrow$default
|
||||
package test
|
||||
|
||||
enum class TarEnum {
|
||||
OK
|
||||
}
|
||||
inline fun <reified T : Enum<T>> String?.enumOrNull(): T? {
|
||||
this ?: return null
|
||||
return enumValues<T>().firstOrNull { it.name == this }
|
||||
}
|
||||
|
||||
inline fun <reified T : Enum<T>> String?.enumOrThrow(handleNull: () -> Throwable = { IllegalArgumentException("Enum type ${T::class.java} not contain value=$this") }): T {
|
||||
return this.enumOrNull<T>() ?: throw handleNull()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return "OK".enumOrThrow<TarEnum>()!!.name
|
||||
}
|
||||
Reference in New Issue
Block a user