FIR: introduce ILLEGAL_SUSPEND_FUNCTION_CALL & PROPERTY_ACCESS diagnostics

This commit is contained in:
Mikhail Glukhikh
2021-07-20 16:36:43 +03:00
committed by teamcityserver
parent e4992176c1
commit 8f1d07084b
33 changed files with 147 additions and 222 deletions
@@ -1,29 +0,0 @@
// !LANGUAGE: +UnrestrictedBuilderInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Builder<T> {
suspend fun add(t: T) {}
}
fun <S> build(g: suspend Builder<S>.() -> Unit): List<S> = TODO()
fun <S> wrongBuild(g: Builder<S>.() -> Unit): List<S> = TODO()
fun <S> Builder<S>.extensionAdd(s: S) {}
suspend fun <S> Builder<S>.safeExtensionAdd(s: S) {}
val member = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>build<!> {
add(42)
}
val memberWithoutAnn = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>wrongBuild<!> {
add(42)
}
val extension = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>build<!> {
extensionAdd("foo")
}
val safeExtension = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>build<!> {
safeExtensionAdd("foo")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +UnrestrictedBuilderInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -1,53 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// SKIP_TXT
import kotlin.coroutines.*
fun ordinal() {
kotlin.coroutines.coroutineContext
coroutineContext
}
suspend fun named() {
kotlin.coroutines.coroutineContext
coroutineContext
}
class A {
val coroutineContextNew = kotlin.coroutines.coroutineContext
val context = coroutineContext
}
class Controller {
fun ordinal() {
kotlin.coroutines.coroutineContext
coroutineContext
}
suspend fun named() {
kotlin.coroutines.coroutineContext
coroutineContext
}
suspend fun severalArgs(s: String, a: Any) {
kotlin.coroutines.coroutineContext
coroutineContext
}
}
fun builder(c: () -> CoroutineContext) = {}
fun builderSuspend(c: suspend () -> CoroutineContext) = {}
fun builderSeveralArgs(c: (Int, Int, Int) -> CoroutineContext) = {}
fun builderSuspendSeveralArgs(c: suspend (Int, Int, Int) -> CoroutineContext) = {}
fun test() {
builder { kotlin.coroutines.coroutineContext }
builder { coroutineContext }
builderSuspend { kotlin.coroutines.coroutineContext }
builderSuspend { coroutineContext }
builderSeveralArgs { _, _, _ -> kotlin.coroutines.coroutineContext }
builderSeveralArgs { _, _, _ -> coroutineContext }
builderSuspendSeveralArgs { _, _, _ -> kotlin.coroutines.coroutineContext }
builderSuspendSeveralArgs { _, _, _ -> coroutineContext }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
// SKIP_TXT
@@ -1,22 +0,0 @@
import Host.bar
object Host {
suspend fun bar() {}
}
suspend fun foo() {}
fun noSuspend() {
foo()
bar()
}
class A {
init {
foo()
bar()
}
}
val x = foo()
val y = bar()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
import Host.bar
object Host {
@@ -1,5 +1,5 @@
fun bar(d: Delegate): String {
val x: String by d
val x: String by <!ILLEGAL_SUSPEND_FUNCTION_CALL!>d<!>
return x
}
@@ -1,27 +0,0 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !LANGUAGE: +NewInference
import kotlin.experimental.ExperimentalTypeInference
interface In<in E> {
fun send(element: E)
}
class InImpl<E> : In<E> {
override fun send(element: E) {}
}
@OptIn(ExperimentalTypeInference::class)
public fun <T> builder(@BuilderInference block: In<T>.() -> Unit) {
InImpl<T>().block()
}
suspend fun yield() {}
fun test() {
builder {
send(run {
yield() // No error but `yield` is not inside "suspension" context actually
})
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !LANGUAGE: +NewInference
@@ -28,6 +28,6 @@ suspend fun calculate() = "OK"
fun box() {
test {
calculate()
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>calculate<!>()
}
}
@@ -18,7 +18,7 @@ interface SuspendRunnable {
// suspend calls possible inside lambda matching to the parameter
inline fun test(crossinline c: suspend () -> Unit) {
c()
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>c<!>()
val o = object : SuspendRunnable {
override suspend fun run() {
c()
@@ -27,6 +27,6 @@ suspend fun calculate() = "OK"
fun box() {
test {
calculate()
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>calculate<!>()
}
}
@@ -1,37 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
// SKIP_TXT
// WITH_COROUTINES
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import helpers.*
interface SuspendRunnable {
suspend fun run()
}
// Function is NOT suspend
// parameter is noinline
// parameter is suspend
// Block is NOT allowed to be called inside the body of owner inline function
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
// It is possible to call startCoroutine on the parameter
// suspend calls possible inside lambda matching to the parameter
inline fun test(noinline c: suspend () -> Unit) {
c()
val o = object : SuspendRunnable {
override suspend fun run() {
c()
}
}
val l: suspend () -> Unit = { c() }
c.startCoroutine(EmptyContinuation)
}
suspend fun calculate() = "OK"
fun box() {
test {
calculate()
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
// SKIP_TXT
// WITH_COROUTINES
@@ -18,7 +18,7 @@ interface SuspendRunnable {
// suspend calls possible inside lambda matching to the parameter
inline fun test(c: suspend () -> Unit) {
c()
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>c<!>()
val o = object: SuspendRunnable {
override suspend fun run() {
c()
@@ -1,10 +0,0 @@
suspend fun foo1(q: suspend () -> Unit) = q()
suspend fun foo2(x: suspend (Int) -> String) = x(1)
suspend fun foo3(y: suspend String.(Int) -> Double) = "".y(1)
suspend fun String.foo4(y: suspend String.(Int) -> Double) = "".y(1)
fun noSuspend(x: suspend (Int) -> String) {
x(1)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
suspend fun foo1(q: suspend () -> Unit) = q()
suspend fun foo2(x: suspend (Int) -> String) = x(1)
@@ -1,2 +0,0 @@
fun test1(sfn: suspend () -> Unit) = sfn()
fun test2(sfn: suspend () -> Unit) = sfn.invoke()
@@ -1,2 +1,3 @@
// FIR_IDENTICAL
fun test1(sfn: suspend () -> Unit) = <!ILLEGAL_SUSPEND_FUNCTION_CALL!>sfn<!>()
fun test2(sfn: suspend () -> Unit) = sfn.<!ILLEGAL_SUSPEND_FUNCTION_CALL!>invoke<!>()
@@ -1,9 +0,0 @@
val test1: (suspend () -> Unit)? = null
val test2: <!WRONG_MODIFIER_TARGET!>suspend<!> (() -> Unit)? = null
val test3: <!WRONG_MODIFIER_TARGET!>suspend<!> ( (() -> Unit)? ) = null
fun foo() {
test1?.invoke()
test2?.invoke()
test3?.invoke()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
val test1: (suspend () -> Unit)? = null
val test2: <!WRONG_MODIFIER_TARGET!>suspend<!> (() -> Unit)? = null
val test3: <!WRONG_MODIFIER_TARGET!>suspend<!> ( (() -> Unit)? ) = null