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) { - 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) -> 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. 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(