diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index e88010eb130..ba4f672e1d1 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -392,6 +392,19 @@ abstract class FirDataFlowAnalyzer( // ----------------------------------- While Loop ----------------------------------- + private fun exitCommonLoop(exitNode: LoopExitNode) { + val singlePreviousNode = exitNode.previousNodes.singleOrNull { !it.isDead } + if (singlePreviousNode is LoopConditionExitNode) { + val variable = variableStorage.getOrCreateVariable(singlePreviousNode.fir) + exitNode.flow = logicSystem.approveStatementsInsideFlow( + exitNode.flow, + variable eq false, + shouldForkFlow = false, + shouldRemoveSynthetics = true + ) + } + } + fun enterWhileLoop(loop: FirLoop) { val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop) loopEnterNode.mergeIncomingFlow() @@ -407,7 +420,7 @@ abstract class FirDataFlowAnalyzer( loopBlockEnterNode.flow, conditionVariable eq true, shouldForkFlow = false, - shouldRemoveSynthetics = true + shouldRemoveSynthetics = false ) } } @@ -416,6 +429,7 @@ abstract class FirDataFlowAnalyzer( val (blockExitNode, exitNode) = graphBuilder.exitWhileLoop(loop) blockExitNode.mergeIncomingFlow() exitNode.mergeIncomingFlow() + exitCommonLoop(exitNode) } // ----------------------------------- Do while Loop ----------------------------------- @@ -436,6 +450,7 @@ abstract class FirDataFlowAnalyzer( val (loopConditionExitNode, loopExitNode) = graphBuilder.exitDoWhileLoop(loop) loopConditionExitNode.mergeIncomingFlow() loopExitNode.mergeIncomingFlow() + exitCommonLoop(loopExitNode) } // ----------------------------------- Try-catch-finally ----------------------------------- diff --git a/compiler/testData/diagnostics/tests/BreakContinue.fir.kt b/compiler/testData/diagnostics/tests/BreakContinue.fir.kt index 9ed9dad5de2..3f7bfc61058 100644 --- a/compiler/testData/diagnostics/tests/BreakContinue.fir.kt +++ b/compiler/testData/diagnostics/tests/BreakContinue.fir.kt @@ -38,7 +38,7 @@ class C { break; } } - a.compareTo("2") + a.compareTo("2") } fun containsBreakWithLabel(a: String?) { @@ -52,7 +52,7 @@ class C { loop@ while(a == null) { break@label } - a.compareTo("2") + a.compareTo("2") } fun containsBreakToOuterLoop(a: String?, b: String?) { @@ -60,7 +60,7 @@ class C { while(a == null) { break@loop } - a.compareTo("2") + a.compareTo("2") } } diff --git a/compiler/testData/diagnostics/tests/Nullability.fir.kt b/compiler/testData/diagnostics/tests/Nullability.fir.kt index 5e1566d4f02..ec7997d2a2d 100644 --- a/compiler/testData/diagnostics/tests/Nullability.fir.kt +++ b/compiler/testData/diagnostics/tests/Nullability.fir.kt @@ -151,7 +151,7 @@ fun test() { out2?.println(); out2.println(); } - out2.println() + out2.println() } @@ -228,7 +228,7 @@ fun f6(s : String?) { do { s?.get(0) } while (s == null) - s.get(0) + s.get(0) } fun f7(s : String?, t : String?) { diff --git a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt index 93e5f16f7e9..e719d154b20 100644 --- a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt +++ b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt @@ -127,12 +127,12 @@ fun f13(a : A?) { fun f14(a : A?) { while (!(a is B)) { } - a.bar() + a.bar() } fun f15(a : A?) { do { } while (!(a is B)) - a.bar() + a.bar() } fun getStringLength(obj : Any) : Char? { diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/doWhileNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/doWhileNull.fir.kt index 92da461b994..e1486b9d8a7 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/doWhileNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/doWhileNull.fir.kt @@ -1,5 +1,5 @@ fun foo(s: String?): Int { do { } while (s==null) - return s.length + return s.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhile.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhile.fir.kt index 19529e706b5..e3f2f17e3bc 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhile.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhile.fir.kt @@ -7,7 +7,7 @@ public fun foo(p: String?, r: String?): Int { } while (r == null) } while (!x()) // Auto cast possible - r.length + r.length // Auto cast possible return p.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhileWithLongContinue.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhileWithLongContinue.fir.kt index 6564b86a853..9d4e2a83221 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhileWithLongContinue.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedDoWhileWithLongContinue.fir.kt @@ -8,7 +8,7 @@ public fun foo(p: String?, r: String?): Int { } while (r == null) } while (!x()) // Auto cast NOT possible due to long continue - r.length + r.length // Auto cast possible return p.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoops.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoops.fir.kt index 225304cab01..3a9ca1b960c 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoops.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoops.fir.kt @@ -11,7 +11,7 @@ public fun foo(p: String?, r: String?, q: String?): Int { if (!x()) break } // Smart cast is possible everywhere - r.length + r.length q.length return p.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsShort.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsShort.fir.kt index cdb92f855d4..0cc9f22c46c 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsShort.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsShort.fir.kt @@ -9,7 +9,7 @@ public fun foo(p: String?, r: String?, q: String?): Int { if (!x()) break } // Smart cast is possible everywhere - r.length + r.length q.length return p.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithBreak.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithBreak.fir.kt index 82a688b33ba..8447c8f7f14 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithBreak.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithBreak.fir.kt @@ -12,7 +12,7 @@ public fun foo(p: String?, r: String?, q: String?): Int { if (!x()) break } // Smart cast is possible everywhere - r.length + r.length q.length return p.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithLongContinue.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithLongContinue.fir.kt index 8cde16df1b4..d33b5f010f6 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithLongContinue.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/nestedLoopsWithLongContinue.fir.kt @@ -14,6 +14,6 @@ public fun foo(p: String?, r: String?, q: String?): Int { // Smart cast is possible only for q q.length // But not possible for the others - r.length + r.length return p.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/whileNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/whileNull.fir.kt index 1482762bde8..fe3b139995d 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/whileNull.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/whileNull.fir.kt @@ -1,5 +1,5 @@ fun foo(s: String?): Int { while (s==null) { } - return s.length + return s.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/whileNullAssignToSomething.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/whileNullAssignToSomething.fir.kt index 276b68eeccc..cb8507ce259 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/whileNullAssignToSomething.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/whileNullAssignToSomething.fir.kt @@ -5,5 +5,5 @@ fun main() { if (i == 10) result = "non null" else i++ } - result.length + result.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/variables/ifElseBlockInsideDoWhile.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/variables/ifElseBlockInsideDoWhile.fir.kt index 9d04156c7d9..5478cf42c19 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/variables/ifElseBlockInsideDoWhile.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/variables/ifElseBlockInsideDoWhile.fir.kt @@ -11,5 +11,5 @@ public fun foo(xx: Any): Int { // y!! in both branches y.length } while (!(x is String)) - return x.length + return x.length } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/nestedDoWhile.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/nestedDoWhile.fir.kt index e08d47a1ce4..6c18cbbe77c 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/nestedDoWhile.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/nestedDoWhile.fir.kt @@ -9,7 +9,7 @@ public fun foo(pp: String?, rr: String?): Int { } while (r == null) } while (!x()) // Auto cast possible - r.length + r.length // Auto cast possible return p.length } \ No newline at end of file