Add additional checks for RestrictsSuspension-marked functions

Namely, check that when one calls a restricted function
the reciever used for that calls is obtained exactly from the enclosing
suspend function

 #KT-24859 Fixed
This commit is contained in:
Denis Zharkov
2018-06-20 20:00:10 +03:00
parent 35fdfc9f05
commit 5c04a302fa
6 changed files with 279 additions and 17 deletions
@@ -0,0 +1,62 @@
// COMMON_COROUTINES_TEST
// SKIP_TXT
@COROUTINES_PACKAGE.RestrictsSuspension
class RestrictedController {
suspend fun member() {
ext()
member()
memberExt()
}
suspend fun RestrictedController.memberExt() {
ext()
member()
memberExt()
}
}
suspend fun RestrictedController.ext() {
ext()
member()
memberExt()
}
fun generate(<!UNUSED_PARAMETER!>c<!>: suspend RestrictedController.() -> Unit) {}
fun runBlocking(<!UNUSED_PARAMETER!>x<!>: suspend () -> Unit) {}
fun test() {
generate a@{
ext()
member()
memberExt()
this@a.ext()
this@a.member()
this@a.memberExt()
generate b@{
ext()
member()
memberExt()
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>ext<!>()
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>member<!>()
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>memberExt<!>()
this@b.ext()
this@b.member()
this@b.memberExt()
}
runBlocking {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>ext<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>member<!>()
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>memberExt<!>()
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>ext<!>()
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>member<!>()
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>memberExt<!>()
}
}
}
@@ -0,0 +1,91 @@
// COMMON_COROUTINES_TEST
// SKIP_TXT
@COROUTINES_PACKAGE.RestrictsSuspension
class RestrictedController<T> {
suspend fun yield(<!UNUSED_PARAMETER!>x<!>: T) {}
suspend fun anotherYield(x: T) {
yield(x)
this.yield(x)
yield2(x)
this.yield2(x)
with(this) {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(x)
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(x)
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(x)
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(x)
}
}
}
fun <T> buildSequence(<!UNUSED_PARAMETER!>c<!>: suspend RestrictedController<T>.() -> Unit) {}
suspend fun <T> RestrictedController<T>.yield2(<!UNUSED_PARAMETER!>x<!>: T) {}
fun test() {
buildSequence<Int> a@{
buildSequence<Int> b@{
yield(1)
yield2(1)
this@b.yield(1)
this@b.yield2(1)
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(2) // Should be error
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(2) // Should be error
with(this) {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(3)
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(3)
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(3)
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(3)
}
}
}
buildSequence<Int> {
buildSequence<String> {
yield("a")
yield2("a")
this.yield("b")
this.yield2("b")
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(1) // Should be error
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(1) // Should be error
with(this) {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>("")
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>("")
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>("")
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>("")
}
}
}
buildSequence<Int> a@{
yield(1)
yield2(1)
buildSequence {
yield("")
yield2("")
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>(1)
this@a.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>(1)
with(this) {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>("")
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>("")
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>("")
this@with.<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield2<!>("")
}
}
}
buildSequence<String> {
yield("")
RestrictedController<String>().<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>("1")
}
}
@@ -0,0 +1,18 @@
// COMMON_COROUTINES_TEST
// SKIP_TXT
@COROUTINES_PACKAGE.RestrictsSuspension
class RestrictedController {
suspend fun yield() {}
}
fun generate(<!UNUSED_PARAMETER!>c<!>: suspend RestrictedController.() -> Unit) {}
fun runBlocking(<!UNUSED_PARAMETER!>x<!>: suspend () -> Unit) {}
fun test() {
generate {
runBlocking {
<!ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL!>yield<!>()
}
}
}