diff --git a/crates/mun_codegen/src/ir/body.rs b/crates/mun_codegen/src/ir/body.rs index 600661cc3..20d4c9df0 100644 --- a/crates/mun_codegen/src/ir/body.rs +++ b/crates/mun_codegen/src/ir/body.rs @@ -488,8 +488,12 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { } }; } - tail.and_then(|expr| self.gen_expr(expr)) - .or_else(|| Some(self.gen_empty())) + + if let Some(tail) = tail { + self.gen_expr(tail) + } else { + Some(self.gen_empty()) + } } /// Constructs a builder that should be used to emit an `alloca` instruction. These instructions @@ -1105,7 +1109,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { if !self.infer[*else_branch].is_never() { self.builder.build_unconditional_branch(&merge_block); } - result_ir.map(|res| (res, self.builder.get_insert_block().unwrap())) + Some((result_ir, self.builder.get_insert_block().unwrap())) } else { None }; @@ -1117,13 +1121,15 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> { // Construct phi block if a value was returned if let Some(then_block_ir) = then_block_ir { - if let Some((else_block_ir, else_block)) = else_ir_and_block { + if let Some((Some(else_block_ir), else_block)) = else_ir_and_block { let phi = self.builder.build_phi(then_block_ir.get_type(), "iftmp"); phi.add_incoming(&[(&then_block_ir, &then_block), (&else_block_ir, &else_block)]); Some(phi.as_basic_value()) } else { Some(then_block_ir) } + } else if let Some((else_block_ir, _else_block)) = else_ir_and_block { + else_block_ir } else { Some(self.gen_empty()) } diff --git a/crates/mun_codegen/src/snapshots/test__issue_228.snap b/crates/mun_codegen/src/snapshots/test__issue_228.snap new file mode 100644 index 000000000..9d16113d9 --- /dev/null +++ b/crates/mun_codegen/src/snapshots/test__issue_228.snap @@ -0,0 +1,38 @@ +--- +source: crates/mun_codegen/src/test.rs +expression: "pub fn fact(n: usize) -> usize {\n \t if n == 0 {return 1} else {n * (n-1)}\n}" +--- +; == FILE IR ===================================== +; ModuleID = 'main.mun' +source_filename = "main.mun" + +%struct.MunTypeInfo = type { [16 x i8], i8*, i32, i8, i8 } + +@global_type_table = external global [1 x %struct.MunTypeInfo*] + +define i64 @fact(i64) { +body: + %eq = icmp eq i64 %0, 0 + br i1 %eq, label %then, label %else + +then: ; preds = %else, %body + %merge = phi i64 [ 1, %body ], [ %mul, %else ] + ret i64 %merge + +else: ; preds = %body + %sub = sub i64 %0, 1 + %mul = mul i64 %0, %sub + br label %then +} + + +; == GROUP IR ==================================== +; ModuleID = 'group_name' +source_filename = "group_name" + +%struct.MunTypeInfo = type { [16 x i8], i8*, i32, i8, i8 } + +@"type_info::::name" = private unnamed_addr constant [10 x i8] c"core::u64\00" +@"type_info::" = private unnamed_addr constant %struct.MunTypeInfo { [16 x i8] c"\A6\E7g \D1\8B\1Aq`\1F\1E\07\BB5@q", [10 x i8]* @"type_info::::name", i32 64, i8 8, i8 0 } +@global_type_table = constant [1 x %struct.MunTypeInfo*] [%struct.MunTypeInfo* @"type_info::"] + diff --git a/crates/mun_codegen/src/snapshots/test__issue_228_never_if.snap b/crates/mun_codegen/src/snapshots/test__issue_228_never_if.snap new file mode 100644 index 000000000..0b8985224 --- /dev/null +++ b/crates/mun_codegen/src/snapshots/test__issue_228_never_if.snap @@ -0,0 +1,37 @@ +--- +source: crates/mun_codegen/src/test.rs +expression: "pub fn fact(n: usize) -> usize {\n \t if n == 0 {return 1} else {return n * (n-1)}\n \t return 2;\n}" +--- +; == FILE IR ===================================== +; ModuleID = 'main.mun' +source_filename = "main.mun" + +%struct.MunTypeInfo = type { [16 x i8], i8*, i32, i8, i8 } + +@global_type_table = external global [1 x %struct.MunTypeInfo*] + +define i64 @fact(i64) { +body: + %eq = icmp eq i64 %0, 0 + br i1 %eq, label %then, label %else + +then: ; preds = %body + ret i64 1 + +else: ; preds = %body + %sub = sub i64 %0, 1 + %mul = mul i64 %0, %sub + ret i64 %mul +} + + +; == GROUP IR ==================================== +; ModuleID = 'group_name' +source_filename = "group_name" + +%struct.MunTypeInfo = type { [16 x i8], i8*, i32, i8, i8 } + +@"type_info::::name" = private unnamed_addr constant [10 x i8] c"core::u64\00" +@"type_info::" = private unnamed_addr constant %struct.MunTypeInfo { [16 x i8] c"\A6\E7g \D1\8B\1Aq`\1F\1E\07\BB5@q", [10 x i8]* @"type_info::::name", i32 64, i8 8, i8 0 } +@global_type_table = constant [1 x %struct.MunTypeInfo*] [%struct.MunTypeInfo* @"type_info::"] + diff --git a/crates/mun_codegen/src/test.rs b/crates/mun_codegen/src/test.rs index 163528b92..7d9422915 100644 --- a/crates/mun_codegen/src/test.rs +++ b/crates/mun_codegen/src/test.rs @@ -7,6 +7,29 @@ use mun_target::spec::Target; use std::cell::RefCell; use std::sync::Arc; +#[test] +fn issue_228_never_if() { + test_snapshot( + r#" + pub fn fact(n: usize) -> usize { + if n == 0 {return 1} else {return n * (n-1)} + return 2; + } + "#, + ) +} + +#[test] +fn issue_228() { + test_snapshot( + r#" + pub fn fact(n: usize) -> usize { + if n == 0 {return 1} else {n * (n-1)} + } + "#, + ) +} + #[test] fn issue_128() { test_snapshot(