Fixes for inline fun finally block generation before lambda non-local returns
This commit is contained in:
+64
@@ -0,0 +1,64 @@
|
||||
import test.*
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
class MyException(message: String) : Exception(message)
|
||||
|
||||
class Holder(var value: String) {
|
||||
public fun plusAssign(s: String?) {
|
||||
value += s
|
||||
if (s != "closed") {
|
||||
value += "->"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Test() : MCloseable {
|
||||
|
||||
val status = Holder("")
|
||||
|
||||
private fun jobFun() {
|
||||
status += "called"
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinally(): Holder {
|
||||
muse {
|
||||
try {
|
||||
jobFun()
|
||||
throw MyException("exception")
|
||||
}
|
||||
catch (e: MyException) {
|
||||
status += e.getMessage()
|
||||
return status
|
||||
}
|
||||
finally {
|
||||
status += "finally"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
status += "closed"
|
||||
throw MyException("error")
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
assertError(1, "called->exception->finally->closed") {
|
||||
nonLocalWithExceptionAndFinally()
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
public fun assertError(index: Int, expected: String, l: Test.()->Unit) {
|
||||
val testLocal = Test()
|
||||
try {
|
||||
testLocal.l()
|
||||
fail("fail $index: no error")
|
||||
} catch (e: Exception) {
|
||||
assertEquals(expected, testLocal.status.value, "failed on $index")
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package test
|
||||
|
||||
public trait MCloseable {
|
||||
public open fun close()
|
||||
}
|
||||
|
||||
public inline fun <T : MCloseable, R> T.muse(block: (T) -> R): R {
|
||||
try {
|
||||
return block(this)
|
||||
} finally {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
import test.*
|
||||
|
||||
|
||||
fun test0(
|
||||
h: Holder,
|
||||
throwExternalFinEx1: Boolean = false,
|
||||
res: String = "Fail"
|
||||
): String {
|
||||
try {
|
||||
val localResult = doCall (
|
||||
{
|
||||
h += "OK_NON_LOCAL"
|
||||
return "OK_NON_LOCAL"
|
||||
},
|
||||
{
|
||||
h += "OK_FINALLY1"
|
||||
"OK_FINALLY1"
|
||||
},
|
||||
{
|
||||
h += "innerTryBlock"
|
||||
if (throwExternalFinEx1) {
|
||||
throw Exception1("EXCEPTION_IN_EXTERNAL_FINALLY")
|
||||
}
|
||||
"innerTryBlock"
|
||||
},
|
||||
{
|
||||
h += "CATCHBLOCK"
|
||||
"CATCHBLOCK"
|
||||
},
|
||||
res)
|
||||
return localResult;
|
||||
} catch(e: Exception1) {
|
||||
return e.getMessage()!!
|
||||
} catch(e: Exception2) {
|
||||
return e.getMessage()!!
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var h = Holder()
|
||||
var test0 = test0(h, res = "OK")
|
||||
if (test0 != "OK_NON_LOCAL" || h.value != "OK_NON_LOCAL -> OK_FINALLY1 -> innerTryBlock") return "test0_1: ${test0}, holder: ${h.value}"
|
||||
|
||||
h = Holder()
|
||||
test0 = test0(h, throwExternalFinEx1 = true, res = "OK")
|
||||
if (test0 != "OK_NON_LOCAL" || h.value != "OK_NON_LOCAL -> OK_FINALLY1 -> innerTryBlock -> CATCHBLOCK") return "test0_2: ${test0}, holder: ${h.value}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package test
|
||||
|
||||
public class Holder(var value: String = "") {
|
||||
|
||||
public fun plusAssign(s: String?) {
|
||||
if (value.length != 0) {
|
||||
value += " -> "
|
||||
}
|
||||
value += s
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Exception1(message: String) : java.lang.RuntimeException(message)
|
||||
|
||||
public class Exception2(message: String) : java.lang.RuntimeException(message)
|
||||
|
||||
public inline fun doCall(block: ()-> String, finallyBlock: ()-> String,
|
||||
tryBlock2: ()-> String, catchBlock2: ()-> String, res: String = "Fail") : String {
|
||||
try {
|
||||
block()
|
||||
}
|
||||
finally {
|
||||
finallyBlock()
|
||||
try {
|
||||
tryBlock2()
|
||||
} catch (e: Exception) {
|
||||
catchBlock2()
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
inline fun test(s: ()->Int): Int {
|
||||
var i = 0;
|
||||
i = s()
|
||||
try {
|
||||
i = i + 10
|
||||
} finally {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
var p: Int = 1
|
||||
test {
|
||||
try {
|
||||
p = 1
|
||||
return "OK" //finally from inline fun doen't split this try
|
||||
} catch(e: Exception) {
|
||||
p = -1;
|
||||
p
|
||||
} finally {
|
||||
p++
|
||||
}
|
||||
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
// 10 TRYCATCHBLOCK
|
||||
@@ -0,0 +1,55 @@
|
||||
inline fun test(s: ()->Int): Int {
|
||||
var i = 0;
|
||||
try {
|
||||
i = s()
|
||||
i = i + 10
|
||||
} finally {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
var p: Int = 1
|
||||
test {
|
||||
try {
|
||||
p = 1
|
||||
return "OK" //finally from inline fun doen't split this try
|
||||
} catch(e: Exception) {
|
||||
p = -1;
|
||||
p
|
||||
} finally {
|
||||
p++
|
||||
}
|
||||
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
// maybe we shouldinline fun test(s: ()->Int): Int {
|
||||
var i = 0;
|
||||
try {
|
||||
i = s()
|
||||
i = i + 10
|
||||
} finally {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
var p: Int = 1
|
||||
test {
|
||||
try {
|
||||
p = 1
|
||||
return "OK" //finally from inline fun doen't split this try
|
||||
} catch(e: Exception) {
|
||||
p = -1;
|
||||
p
|
||||
} finally {
|
||||
p++
|
||||
}
|
||||
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
check test data
|
||||
// 13 TRYCATCHBLOCK
|
||||
Reference in New Issue
Block a user