2c06503311
The fields containing crossinline lambdas should be package-private to
avoid generating synthetic accessors, which break object regeneration.
Note that the inline methods cannot actually be called, as call sites
will attempt to read the captured lambda from a field through a *copy*
of the local containing the object, so these reads will not be inlined,
causing an exception at runtime:
inline fun f(crossinline g: () -> Unit) = object : I {
inline fun h() = g()
// effectively `val tmp = this; return tmp.$g()`:
override fun run() = h()
}
f {}.run() // NoSuchFieldError: $g
This particular example can be fixed by reusing locals for receiver
parameters in IrInlineCodegen, but explicitly assigning `this` to
another variable and calling an inline method on it will break it again.
(This is only applicable to the JVM_IR backend, as the non-IR one fails
to generate `f` at all for some other reason.)
21 lines
446 B
Kotlin
Vendored
21 lines
446 B
Kotlin
Vendored
// FILE: 1.kt
|
|
package test
|
|
|
|
interface I {
|
|
fun f(): String
|
|
}
|
|
|
|
inline fun test(crossinline h: () -> String) = object : I {
|
|
// TODO: actually call g() in f() -- currently, the inliner fails to detect
|
|
// an inlined read of h's field because it uses a copy of `this`
|
|
// as a receiver
|
|
override fun f(): String = h()
|
|
inline fun g(): String = h()
|
|
}
|
|
|
|
// FILE: 2.kt
|
|
|
|
import test.*
|
|
|
|
fun box(): String = test { "OK" }.f()
|