Repository: intellij-rust/intellij-rust
Issue: Wrong control-flow of break/continue inside block expressions

## Environment

* **IntelliJ Rust plugin version:** 0.3.141.3638-203-nightly
* **Rust toolchain version:** 1.48.0 (7eac88abb 2020-11-16) x86_64-apple-darwin
* **IDE name and version:** IntelliJ IDEA 2020.3.2 Preview Ultimate Edition (IU-203.7148.15)
* **Operating system:** macOS 10.16
* **Macro expansion engine:** new
* **Name resolution engine:** new

## Problem description
`break` and `continue` located inside block expressions break control-flow/data-flow analysis, e.g. liveness analysis:
```Rust
fn main() {
    let x = 1; // false-positive: Variable `x` is never used
    loop {
        {
            break;
        }
    }
    println!("{}", x);
}
```


Changed files:
src/test/kotlin/org/rust/lang/core/dfa/RsControlFlowGraphTest.kt, src/main/kotlin/org/rust/lang/core/dfa/CFGBuilder.kt, src/test/kotlin/org/rust/ide/inspections/lints/RsLivenessInspectionTest.kt

diff --git a/src/main/kotlin/org/rust/lang/core/dfa/CFGBuilder.kt b/src/main/kotlin/org/rust/lang/core/dfa/CFGBuilder.kt
index a6f47710c..b8add718d 100644
--- a/src/main/kotlin/org/rust/lang/core/dfa/CFGBuilder.kt
+++ b/src/main/kotlin/org/rust/lang/core/dfa/CFGBuilder.kt
@@ -28,7 +28,7 @@ class CFGBuilder(
 ) : RsVisitor() {
     data class BlockScope(val blockExpr: RsBlockExpr, val breakNode: CFGNode)
 
-    data class LoopScope(val loop: RsLabeledExpression, val continueNode: CFGNode, val breakNode: CFGNode)
+    data class LoopScope(val loop: RsLooplikeExpr, val continueNode: CFGNode, val breakNode: CFGNode)
 
     enum class ScopeCFKind {
         Break, Continue;
@@ -135,7 +135,7 @@ class CFGBuilder(
             }
         } else {
             // otherwise, try to find the corresponding loop
-            val exprBlock = expr.ancestors.filterIsInstance<RsLabeledExpression>().firstOrNull()?.block
+            val exprBlock = expr.ancestors.filterIsInstance<RsLooplikeExpr>().firstOrNull()?.block
 
             for ((loop, continueNode, breakNode) in loopScopes) {
                 if (loop.block == exprBlock) {
diff --git a/src/test/kotlin/org/rust/ide/inspections/lints/RsLivenessInspectionTest.kt b/src/test/kotlin/org/rust/ide/inspections/lints/RsLivenessInspectionTest.kt
index 74386224d..55fd5b2bb 100644
--- a/src/test/kotlin/org/rust/ide/inspections/lints/RsLivenessInspectionTest.kt
+++ b/src/test/kotlin/org/rust/ide/inspections/lints/RsLivenessInspectionTest.kt
@@ -803,4 +803,16 @@ class RsLivenessInspectionTest : RsInspectionsTestBase(RsLivenessInspection::cla
             a;
         }
     """)
+
+    fun `test use after loop with break inside block expr`() = checkByText("""
+        fn main() {
+            let x = 1;
+            loop {
+                {
+                    break;
+                }
+            }
+            x;
+        }
+    """)
 }
diff --git a/src/test/kotlin/org/rust/lang/core/dfa/RsControlFlowGraphTest.kt b/src/test/kotlin/org/rust/lang/core/dfa/RsControlFlowGraphTest.kt
index a9243e45e..1bb3134f7 100644
--- a/src/test/kotlin/org/rust/lang/core/dfa/RsControlFlowGraphTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/dfa/RsControlFlowGraphTest.kt
@@ -998,6 +998,28 @@ class RsControlFlowGraphTest : RsTestBase() {
         Exit
     """)
 
+    fun `test loop with break inside block expr`() = testCFG("""
+        fn main() {
+            loop {
+                {
+                    break;
+                }
+            }
+            1;
+        }
+    """, """
+        Entry
+        Dummy
+        break
+        LOOP
+        LOOP;
+        1
+        1;
+        BLOCK
+        Exit
+        Termination
+    """)
+
     private fun testCFG(@Language("Rust") code: String, expectedIndented: String) {
         InlineFile(code)
         val function = myFixture.file.descendantsOfType<RsFunction>().firstOrNull() ?: return