[JS IR] Introduce the GENERATE_INLINE_ANONYMOUS_FUNCTIONS feature flag

This commit is contained in:
Sergej Jaskiewicz
2022-04-20 14:00:18 +03:00
committed by Space
parent c10af22b27
commit e03747ea7d
18 changed files with 245 additions and 17 deletions
@@ -0,0 +1,60 @@
// KT-51133
package foo
fun <T, R> myWith(t: T, f: (T) -> R) = f(t)
// CHECK_CONTAINS_NO_CALLS: noCapture except=myWith
// HAS_NO_CAPTURED_VARS: function=noCapture except=myWith;noCapture$lambda
fun noCapture() = myWith(42) { it }
// CHECK_CONTAINS_NO_CALLS: captureLocalVariableReadOnly except=myWith IGNORED_BACKENDS=JS
// HAS_NO_CAPTURED_VARS: function=captureLocalVariableReadOnly except=myWith IGNORED_BACKENDS=JS
fun captureLocalVariableReadOnly(a: Int) = myWith(1) { a + it }
// CHECK_CONTAINS_NO_CALLS: captureLocalVariableReadWrite except=myWith IGNORED_BACKENDS=JS
// HAS_NO_CAPTURED_VARS: function=captureLocalVariableReadWrite except=myWith IGNORED_BACKENDS=JS
fun captureLocalVariableReadWrite(): Int {
var a = 41
return myWith(1) {
a += it
a
}
}
val thirteen = 13
// CHECK_CONTAINS_NO_CALLS: captureGlobalVariable except=myWith
// HAS_NO_CAPTURED_VARS: function=captureGlobalVariable except=myWith;captureGlobalVariable$lambda
fun captureGlobalVariable() = myWith(2) { thirteen * it }
class A(val i: Int) {
fun captureClassField() = myWith(100) { it + i }
inner class B(val j: Int) {
inner class C(val k: Int) {
fun captureInnerClassField() = myWith(200) { it + i + j + k }
fun unusedLambda() {
{ i + j + k }
}
}
}
}
fun unusedLambda(f: () -> Unit) {
{ f() }
}
fun box(): String {
if (noCapture() != 42) return "fail noCapture()"
if (captureLocalVariableReadOnly(41) != 42) return "fail captureLocalVariableReadOnly(41)"
if (captureLocalVariableReadWrite() != 42) return "fail captureLocalVariableReadWrite()"
if (captureGlobalVariable() != 26) return "fail captureGlobalVariable()"
if (A(23).captureClassField() != 123) return "fail A(23).captureClassField()"
if (A(300).B(400).C(500).captureInnerClassField() != 1400) return "A(300).B(400).C(500).captureInnerClassField()"
return "OK"
}
@@ -0,0 +1,25 @@
// KT-4237 With in with
package foo
class A {
val ok = "OK"
}
class B
fun <T> with(o: T, body: T.() -> Unit) {
o.body()
}
fun box(): String {
var o = ""
with(A()) {
with(B()) {
o = ok
}
}
return o
}
@@ -0,0 +1,29 @@
// FILE: 1.kt
package test
interface A {
fun run()
}
inline fun testNested(crossinline f: (String) -> Unit) {
object : A {
override fun run() {
f("OK")
}
}.run()
}
inline fun test(crossinline f: (String) -> Unit) {
testNested { it -> { f(it) }()}
}
// FILE: 2.kt
import test.*
fun box(): String {
var result = "fail"
test { it -> result = it }
return result
}
@@ -0,0 +1,29 @@
// FILE: 1.kt
package test
inline fun <T> inlineFun(arg: T, f: (T) -> Unit) {
f(arg)
}
// FILE: 2.kt
import test.*
fun box(): String {
val param = "start"
var result = "fail"
inlineFun("1") { c ->
{
inlineFun("2") { a ->
{
{
result = param + c + a
}()
}()
}
}()
}
return if (result == "start12") "OK" else "fail: $result"
}
@@ -0,0 +1,16 @@
fun <T> bar(x: T, y: (T) -> Boolean): Boolean = y(x) && jsTypeOf(x.asDynamic()) != "number"
fun typeOf(x: dynamic) = js("typeof x")
fun box(): String {
val f = { x: Char ->
val a: Char = x
val b: Any = x
typeOf(a) == "number" && typeOf(b) == "object"
}
if (!f('Q')) return "fail1"
if (!bar('W', f)) return "fail2"
return "OK"
}
@@ -0,0 +1,30 @@
// KJS_WITH_FULL_RUNTIME
package foo
fun box(): String {
val oneTwo = Array(2) {
it + 1
}
val a = ArrayList<() -> Int>()
for (i in oneTwo) {
for (l in 1..2) {
val j = l
a.add({
var res = 0
for (t in 0..2) {
res += i * j
}
res
})
}
}
var sum = 0
for (f in a) {
sum += f()
}
if (sum != 27) return "fail: $sum"
return "OK"
}
@@ -0,0 +1,26 @@
// WITH_STDLIB
// WITH_COROUTINES
// FILE: 1.kt
package test
inline fun foo(crossinline x: () -> Unit) = suspend {
try { } finally {
// This object is regenerated twice (normal return & "catch Throwable, execute finally, and rethrow")
// It doesn't *need* to be, but this should work regardless.
{ x() }()
}
}
// FILE: 2.kt
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import test.*
var result = "fail"
fun box(): String {
suspend {
foo { result = "OK" }()
}.startCoroutine(EmptyContinuation)
return result
}