Files
kotlin-fork/compiler/testData/codegen/boxInline/noInline/noInlineLambdaChainWithCapturedInline.kt
T
pyos 4fc1bd9ec5 Support inlining functions with KT-28064 style objects
Namely, anonymous objects defined in lambdas that have all captured
variables as loose fields instead of a single reference to the parent.

The question is, when a lambda inside an inline function defines an
anonymous object, and that object is not regenerated during codegen for
the inline function itself, but then has to be regenerated at call site
anyway, do we use an outer `this` or loose capture fields? For example,
before KT-28064:

    inline fun f1(g: () -> Unit) = object { g() }
    // -> f1$1 { $g: () -> Unit }
    inline fun f2(g: () -> Unit) = f1 { object { g() } }
    // -> f2$$inlined$f1$1 { $g: () -> Unit }
    //    f2$$inlined$f1$1$lambda$1 { this$0: f2$$inlined$f1$1 }
    inline fun f3(g: () -> Unit) = f2 { object { g() } }
    // -> f3$$inlined$f2$1 { $g: () -> Unit }
    //    f3$$inlined$f2$1$1 { this$0: f3$$inlined$f2$1 }
    //    f3$$inlined$f2$1$1$lambda$1 { this$0: f3$$inlined$f2$1$1 }

After KT-28064:

    inline fun f2(g: () -> Unit) = f1 { object { g() } }
    // -> f2$$inlined$f1$1 { $g: () -> Unit }
    //    f2$1$1 { $g: () -> Unit }
    inline fun f3(g: () -> Unit) = f2 { object { g() } }
    // -> f3$$inlined$f2$1 { $g: () -> Unit }
    //    f3$$inlined$f2$2 { ??? }
    //    f3$1$1 { $g: () -> Unit }

Should `???` be `this$0: f3$$inlined$f2$1` or `$g: () -> Unit`? This
commit chooses the latter for KT-28064 bytecode and keeps `this$0` when
inlining the old bytecode.
2019-11-06 13:11:44 +01:00

85 lines
2.1 KiB
Kotlin
Vendored

// FILE: 1.kt
package test
inline fun <T> inlineFun(arg: T, f: (T) -> Unit) {
f(arg)
}
// FILE: 2.kt
//NO_CHECK_LAMBDA_INLINING
import test.*
inline fun test1(crossinline param: () -> String): String {
var result = "fail"
inlineFun("1") { c ->
{
inlineFun("2") { a ->
{
{
result = param() + c + a
}()
}()
}
}()
}
return result
}
inline fun test2(crossinline param: () -> String): String {
var result = "fail"
inlineFun("2") { a ->
{
{
result = param() + a
}()
}()
}
return result
}
inline fun test3(crossinline param: () -> String): String {
var result = "fail"
inlineFun("2") { d ->
inlineFun("1") { c ->
{
inlineFun("2") { a ->
{
{
result = param() + c + a
}()
}()
}
}()
}
}
return result
}
fun box(): String {
if (test1({"start"}) != "start12") return "fail1: ${test1({"start"})}"
if (test2({"start"}) != "start2") return "fail2: ${test2({"start"})}"
if (test3({"start"}) != "start12") return "fail3: ${test3({"start"})}"
var captured1 = "sta";
val captured2 = "rt";
if (test1({captured1 + captured2}) != "start12") return "fail4: ${test1({captured1 + captured2})}"
if (test2({captured1 + captured2}) != "start2") return "fail5: ${test2({captured1 + captured2})}"
if (test3({captured1 + captured2}) != "start12") return "fail6: ${test3({captured1 + captured2})}"
return {
if (test1 { captured1 + captured2 } != "start12") "fail7: ${test1 { captured1 + captured2 }}"
else if (test2 { captured1 + captured2 } != "start2") "fail8: ${test2 { captured1 + captured2 }}"
else if (test3 { captured1 + captured2 } != "start12") "fail9: ${test3 { captured1 + captured2 }}"
else "OK"
} ()
return "OK"
}