KT-1436 Allow break/continue in inlined lambdas

This commit is contained in:
Pavel Mikhailovskii
2022-08-11 00:12:43 +02:00
committed by teamcity
parent ba7df005a1
commit 8ba80b4b7b
52 changed files with 1851 additions and 88 deletions
@@ -0,0 +1,35 @@
// LANGUAGE: +BreakContinueInInlineLambdas
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: WASM
// WITH_STDLIB
import kotlin.test.assertEquals
inline fun foo(
block1: () -> Unit,
noinline block2: () -> Unit,
block3: () -> Unit
) {
block1()
block2()
block3()
}
fun box(): String {
val visited = mutableListOf<Int>()
for (i in 1..3) {
foo(
{ visited += 1; if (i == 1) continue },
{ visited += 2 },
{ visited += 3; if (i == 2) break },
)
}
assertEquals(listOf(1, 1, 2, 3), visited)
return "OK"
}
@@ -0,0 +1,65 @@
// LANGUAGE: +BreakContinueInInlineLambdas
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: WASM
// WITH_STDLIB
import kotlin.test.assertEquals
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
public annotation class SomeAnnotation
inline fun foo(block: () -> Unit) = block()
fun box(): String {
val visited = mutableListOf<Pair<Int, Int>>()
var i = 0
outer@ while (true) {
i += 1
inner@ for (j in 1..10) {
foo(
(@SomeAnnotation
fun() {
foo(fun() {
foo(@SomeAnnotation {
foo {
if (i == 2) {
continue@outer
}
if (i == 4) {
break@outer
}
if (j == 2) {
continue
}
if (j == 4) {
continue@inner
}
if (j == 6 && i == 1) {
break@inner
}
if (j == 6 && i == 3) {
break
}
}
})
})
})
)
visited += i to j
}
}
assertEquals(listOf(1 to 1, 1 to 3, 1 to 5, 3 to 1, 3 to 3, 3 to 5), visited)
return "OK"
}
@@ -0,0 +1,30 @@
// LANGUAGE: +BreakContinueInInlineLambdas
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: WASM
// WITH_STDLIB
import kotlin.test.assertEquals
inline fun <T> Iterable<T>.myForEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
fun box(): String {
val visited = mutableListOf<Pair<Int, Int>>()
for (i in 1..3) {
(1..3).myForEach { j ->
if (j == 3) {
break
}
visited += i to j
}
}
assertEquals(listOf(1 to 1, 1 to 2), visited)
return "OK"
}
@@ -0,0 +1,17 @@
// LANGUAGE: +BreakContinueInInlineLambdas
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: WASM
inline fun foo(block: () -> Unit) { block() }
fun box(): String {
while (true) {
foo { break }
return "FAIL"
}
return "OK"
}
@@ -0,0 +1,22 @@
// LANGUAGE: +BreakContinueInInlineLambdas
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: WASM
// WITH_STDLIB
import kotlin.test.assertEquals
inline fun <T> Iterable<T>.myForEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
fun box(): String {
while (true) {
"".let { it.run { break } }
}
return "OK"
}
@@ -0,0 +1,18 @@
// LANGUAGE: +BreakContinueInInlineLambdas
// TARGET_BACKEND: JVM_IR
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// TARGET_BACKEND: NATIVE
// TARGET_BACKEND: WASM
inline fun foo(block: () -> Int): Int = block()
fun box(): String {
var sum = 0
for (i in 1..10) {
sum += foo { if (i == 3) break else i }
}
return if (sum == 3) "OK" else "FAIL"
}