[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:
committed by
Space Team
parent
de9826683e
commit
0bd6ea764e
+3
-3
@@ -13,7 +13,7 @@ inline fun test_1(f: () -> Unit) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
inline fun test_2(f: () -> Int): Int {
|
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 {
|
try {
|
||||||
return f()
|
return f()
|
||||||
} finally {
|
} finally {
|
||||||
@@ -54,7 +54,7 @@ inline fun test_5(f: () -> Unit) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
inline fun test_6(f: () -> Int): Int {
|
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 {
|
try {
|
||||||
return f()
|
return f()
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
@@ -78,7 +78,7 @@ inline fun test_7(f: () -> Unit) {
|
|||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
inline fun test_8(f: () -> Int): Int {
|
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 {
|
try {
|
||||||
return f()
|
return f()
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
|
|||||||
+3
-9
@@ -87,12 +87,8 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
graph.exitNode.previousCfgNodes.forEach { node ->
|
graph.exitNode.previousCfgNodes.forEach { node ->
|
||||||
val requiredRange = effectDeclaration.kind
|
val requiredRange = effectDeclaration.kind
|
||||||
val pathAwareInfo = invocationData.getValue(node)
|
val pathAwareInfo = invocationData.getValue(node)
|
||||||
for (info in pathAwareInfo.values) {
|
val info = pathAwareInfo[NormalPath] ?: return@forEach
|
||||||
if (investigate(info, symbol, requiredRange, function, reporter, context)) {
|
investigate(info, symbol, requiredRange, function, reporter, context)
|
||||||
// To avoid duplicate reports, stop investigating remaining paths once reported.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +100,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
function: FirContractDescriptionOwner,
|
function: FirContractDescriptionOwner,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
): Boolean {
|
) {
|
||||||
val foundRange = info[symbol] ?: EventOccurrencesRange.ZERO
|
val foundRange = info[symbol] ?: EventOccurrencesRange.ZERO
|
||||||
if (foundRange !in requiredRange) {
|
if (foundRange !in requiredRange) {
|
||||||
reporter.reportOn(
|
reporter.reportOn(
|
||||||
@@ -115,9 +111,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
foundRange,
|
foundRange,
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class IllegalScopeContext(
|
private class IllegalScopeContext(
|
||||||
|
|||||||
Reference in New Issue
Block a user