Repository: mun-lang/mun (language: rust)

Issue:
'main' panicked at 'internal error: entered unreachable code
Code to reproduce:
```
fn foo() -> i32 {
    let bar = {
        let b = 3;
        return b + 3;
    };

    // This code will never be executed
    let a = 3 + 4;
    a
}
``` 
Tested on mun v0.2.1


Discussion / hints:

Fix patch:
diff --git a/crates/mun_codegen/src/ir/body.rs b/crates/mun_codegen/src/ir/body.rs
index e290fe98a..dd23e0dc8 100644
--- a/crates/mun_codegen/src/ir/body.rs
+++ b/crates/mun_codegen/src/ir/body.rs
@@ -478,7 +478,10 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
                 Statement::Let {
                     pat, initializer, ..
                 } => {
-                    self.gen_let_statement(*pat, *initializer);
+                    // If the let statement never finishes, there is no need to generate more code
+                    if !self.gen_let_statement(*pat, *initializer) {
+                        return None;
+                    }
                 }
                 Statement::Expr(expr) => {
                     // No need to generate code after a statement that has a `never` return type.
@@ -510,9 +513,19 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
         temp_builder
     }
 
-    /// Generate IR for a let statement: `let a:int = 3`
-    fn gen_let_statement(&mut self, pat: PatId, initializer: Option<ExprId>) {
-        let initializer = initializer.and_then(|expr| self.gen_expr(expr));
+    /// Generate IR for a let statement: `let a:int = 3`. Returns `false` if the initializer of the
+    /// statement never returns; `true` otherwise.
+    fn gen_let_statement(&mut self, pat: PatId, initializer: Option<ExprId>) -> bool {
+        let initializer = match initializer {
+            Some(expr) => match self.gen_expr(expr) {
+                Some(expr) => Some(expr),
+                None => {
+                    // If the initializer doesnt return a value it never returns
+                    return false;
+                }
+            },
+            None => None,
+        };
 
         match &self.body[pat] {
             Pat::Bind { name } => {
@@ -534,6 +547,7 @@ impl<'db, 'ink, 't> BodyIrGenerator<'db, 'ink, 't> {
             Pat::Wild => {}
             Pat::Missing | Pat::Path(_) => unreachable!(),
         }
+        true
     }
 
     /// Generates IR for looking up a certain path expression.


Test patch:
diff --git a/crates/mun_codegen/src/snapshots/mun_codegen__test__issue_262.snap b/crates/mun_codegen/src/snapshots/mun_codegen__test__issue_262.snap
new file mode 100644
index 000000000..9c7305121
--- /dev/null
+++ b/crates/mun_codegen/src/snapshots/mun_codegen__test__issue_262.snap
@@ -0,0 +1,18 @@
+---
+source: crates/mun_codegen/src/test.rs
+expression: "fn foo() -> i32 {\n    let bar = {\n        let b = 3;\n        return b + 3;\n    };\n\n    // This code will never be executed\n    let a = 3 + 4;\n    a\n}"
+---
+; == FILE IR =====================================
+; ModuleID = 'main.mun'
+source_filename = "main.mun"
+
+define i32 @foo() {
+body:
+  ret i32 6
+}
+
+
+; == GROUP IR ====================================
+; ModuleID = 'group_name'
+source_filename = "group_name"
+
diff --git a/crates/mun_codegen/src/test.rs b/crates/mun_codegen/src/test.rs
index 6d3f19865..4a21dfd74 100644
--- a/crates/mun_codegen/src/test.rs
+++ b/crates/mun_codegen/src/test.rs
@@ -12,6 +12,23 @@ use inkwell::{context::Context, OptimizationLevel};
 use mun_target::spec::Target;
 use std::{cell::RefCell, sync::Arc};
 
+#[test]
+fn issue_262() {
+    test_snapshot(
+        r"
+    fn foo() -> i32 {
+        let bar = {
+            let b = 3;
+            return b + 3;
+        };
+
+        // This code will never be executed
+        let a = 3 + 4;
+        a
+    }",
+    )
+}
+
 #[test]
 fn issue_225() {
     test_snapshot(