Fix bugs with capturing rhs into EXACTLY_ONCE lambda
There are multiple ways to declare a named variable-like entity in Kotlin: 1. val/var variable declaration 2. destructuring declaration 3. parameter of a function 4. parameter of a lambda 5. destructured lambda parameter 6. for-loop's variable declaration 7. catch block exception declaration 8. val in when 9. field declaration Out of them, only variable and field can be assignable, in other words, they can be on the left hand side of an assignment. Val/var variable declarations were already supported. So, we needed to just support field initialization and tell the backend that other ways are prohibited. Function and lambda parameters were already been supported. So, the only thing to explain to the backend are remaining ways. #KT-39113 Fixed #KT-34048 Fixed
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE, JS
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
fun ok(): String {
|
||||
val res: String
|
||||
val (o, _) = "OK" to "FAIL"
|
||||
runOnce {
|
||||
res = o
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return ok()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
fun foo(): String {
|
||||
var res = "FAIL"
|
||||
try {
|
||||
error("OK")
|
||||
} catch(e: Exception) {
|
||||
runOnce {
|
||||
res = e.message!!
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return foo()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
class Foo {
|
||||
val res: String
|
||||
init {
|
||||
runOnce {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return Foo().res
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
fun test1(): String {
|
||||
var res = ""
|
||||
for (s in listOf("OK")) {
|
||||
runOnce {
|
||||
res += s
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun test2(): String {
|
||||
var res = ""
|
||||
for (s: String in listOf("OK")) {
|
||||
runOnce {
|
||||
res += s
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun test3(): String {
|
||||
var res = ""
|
||||
for ((s, _) in listOf("OK" to "FAIL")) {
|
||||
runOnce {
|
||||
res += s
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun test4(): String {
|
||||
var res = ""
|
||||
for ((s: String, _) in listOf("OK" to "FAIL")) {
|
||||
runOnce {
|
||||
res += s
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
test1().let { if (it != "OK") return "FAIL 1: $it" }
|
||||
test2().let { if (it != "OK") return "FAIL 2: $it" }
|
||||
test3().let { if (it != "OK") return "FAIL 3: $it" }
|
||||
test4().let { if (it != "OK") return "FAIL 4: $it" }
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
fun foo(b: Boolean): String {
|
||||
val res: String
|
||||
runOnce {
|
||||
b
|
||||
res = "OK"
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return foo(true)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
fun o(): String {
|
||||
var res = "FAIL1 "
|
||||
("O" to "").let { (a, _) ->
|
||||
runOnce {
|
||||
res = a
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun k(): String {
|
||||
val res: String
|
||||
"K".let { b ->
|
||||
runOnce {
|
||||
res = b
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return o() + k()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
fun runOnce(action: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
action()
|
||||
}
|
||||
|
||||
fun ok(): String {
|
||||
val res: String
|
||||
when (val o = "OK") {
|
||||
else -> runOnce {
|
||||
res = o
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return ok()
|
||||
}
|
||||
Reference in New Issue
Block a user