[FIR] Consider only normal execution path during contracts verification

There might be several pathes out from the function from CFG point of view:
- normal execution path
- exceptional execution path

For verification of callsInPlace contract it's needed to check only
 the normal path

^KT-63414 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-12-21 13:14:28 +02:00
committed by Space Team
parent de9826683e
commit 0bd6ea764e
2 changed files with 6 additions and 12 deletions
@@ -13,7 +13,7 @@ inline fun test_1(f: () -> Unit) {
@OptIn(ExperimentalContracts::class)
inline fun test_2(f: () -> Int): Int {
<!WRONG_INVOCATION_KIND!>contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }<!> // should be ok
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) } // should be ok
try {
return f()
} finally {
@@ -54,7 +54,7 @@ inline fun test_5(f: () -> Unit) {
@OptIn(ExperimentalContracts::class)
inline fun test_6(f: () -> Int): Int {
<!WRONG_INVOCATION_KIND!>contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }<!> // should be ok
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) } // should be ok
try {
return f()
} catch (_: Exception) {
@@ -78,7 +78,7 @@ inline fun test_7(f: () -> Unit) {
@OptIn(ExperimentalContracts::class)
inline fun test_8(f: () -> Int): Int {
<!WRONG_INVOCATION_KIND!>contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) }<!> // should be error
contract { callsInPlace(f, InvocationKind.EXACTLY_ONCE) } // should be error
try {
return f()
} catch (_: Exception) {
@@ -87,12 +87,8 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
graph.exitNode.previousCfgNodes.forEach { node ->
val requiredRange = effectDeclaration.kind
val pathAwareInfo = invocationData.getValue(node)
for (info in pathAwareInfo.values) {
if (investigate(info, symbol, requiredRange, function, reporter, context)) {
// To avoid duplicate reports, stop investigating remaining paths once reported.
break
}
}
val info = pathAwareInfo[NormalPath] ?: return@forEach
investigate(info, symbol, requiredRange, function, reporter, context)
}
}
}
@@ -104,7 +100,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
function: FirContractDescriptionOwner,
reporter: DiagnosticReporter,
context: CheckerContext
): Boolean {
) {
val foundRange = info[symbol] ?: EventOccurrencesRange.ZERO
if (foundRange !in requiredRange) {
reporter.reportOn(
@@ -115,9 +111,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
foundRange,
context
)
return true
}
return false
}
private class IllegalScopeContext(