Rework check of suspension point inside critical section

There is a trade-off between robustness of check and accuracy of the
diagnostic: the previous version, which works on generation, was too
fragile and lead to false-positives. Now we check on state machine
generation. However, since we do not have PSI for call, we can only
report diagnostic on whole suspend function or suspend lambda.
Additionally, the state machine is generated on crossinline suspend
lambdas regeneration and thus we do not have the PSI for the lambda as
well!

 #KT-27130 Fixed
 #KT-27258 Open
This commit is contained in:
Ilmir Usmanov
2018-09-28 18:20:05 +03:00
parent 1b04945625
commit 281f09f077
8 changed files with 92 additions and 15 deletions
@@ -1,10 +1,13 @@
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:10:13: error: the 'suspensionPoint' suspension point is inside a critical section
suspensionPoint()
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:8:13: error: a suspension point is inside a critical section
builder {
^
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:14:13: error: the 'suspensionPoint' suspension point is inside a critical section
suspensionPoint()
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:14:13: error: a suspension point is inside a critical section
builder {
^
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:19:15: error: the 'suspensionPoint' suspension point is inside a critical section
{ suspensionPoint() }
^
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:20:13: error: a suspension point is inside a critical section
builder {
^
compiler/testData/compileKotlinAgainstCustomBinaries/suspensionPointInMonitor/source.kt:42:9: error: a suspension point is inside a critical section
override suspend fun run() {
^
COMPILATION_ERROR
@@ -9,14 +9,44 @@ fun test() {
synchronized(lock) {
suspensionPoint()
}
}
builder {
inlineMe {
suspensionPoint()
}
}
builder {
monitorInFinally(
{ suspensionPoint() },
{},
{ suspensionPoint() }
)
}
synchronized(lock) {
builder {
suspensionPoint()
}
}
synchronized(lock) {
object : SuspendRunnable {
override suspend fun run() {
suspensionPoint()
}
}
}
object : SuspendRunnable {
override suspend fun run() {
synchronized(lock) {
suspensionPoint()
}
}
}
}
interface SuspendRunnable {
suspend fun run()
}