diff --git a/crates/rune/src/compile/v1/assemble.rs b/crates/rune/src/compile/v1/assemble.rs index bb2929e8a..3790e277c 100644 --- a/crates/rune/src/compile/v1/assemble.rs +++ b/crates/rune/src/compile/v1/assemble.rs @@ -640,17 +640,18 @@ fn condition<'a, 'hir>( match *hir { hir::Condition::Expr(hir) => { let scope = cx.scopes.child(hir)?; - let mut addr = cx.scopes.alloc(hir)?; + let mut addr = cx.scopes.alloc(hir)?.with_name("expression condition"); let asm = if expr(cx, hir, &mut addr)?.converging() { cx.asm.jump_if(addr.addr(), then_label, hir)?; + addr.free()?; Asm::new(hir, (scope, Pattern::Irrefutable)) } else { + addr.free()?; cx.scopes.pop(hir, scope)?; Asm::diverge(hir) }; - addr.free()?; Ok(asm) } hir::Condition::ExprLet(hir) => { @@ -2412,15 +2413,12 @@ fn expr_match<'a, 'hir>( let mut converges = true; if let Some(condition) = branch.condition { - let span = condition; - let mut cond = cx.scopes.defer(condition); - - let scope = cx.scopes.child(span)?; + let scope = cx.scopes.child(condition)?; + let mut cond = cx.scopes.alloc(condition)?.with_name("match condition"); if expr(cx, condition, &mut cond)?.converging() { - cx.asm - .jump_if_not(cond.addr()?.addr(), &match_false, span)?; - cx.asm.jump(&branch_label, span)?; + cx.asm.jump_if_not(cond.addr(), &match_false, condition)?; + cx.asm.jump(&branch_label, condition)?; } else { converges = false; } diff --git a/crates/rune/tests/bug_830.rn b/crates/rune/tests/bug_830.rn index 44617f00a..8a341d94d 100644 --- a/crates/rune/tests/bug_830.rn +++ b/crates/rune/tests/bug_830.rn @@ -36,3 +36,17 @@ fn while_stmt() { assert!(value); } + +#[test] +fn match_stmt() { + let value = true; + + let value2 = match true { + false => false, + _ if value && false => panic!("should not be reached"), + true => true, + }; + + assert!(value); + assert!(value2); +} diff --git a/crates/rune/tests/diverging.rn b/crates/rune/tests/diverging.rn new file mode 100644 index 000000000..df7050748 --- /dev/null +++ b/crates/rune/tests/diverging.rn @@ -0,0 +1,36 @@ +#[test] +fn diverging_if() { + fn inner() { + if return true { + } + + false + } + + assert!(inner()); +} + +#[test] +fn diverging_condition_while() { + fn inner() { + while return true { + } + + false + } + + assert!(inner()); +} + +#[test] +fn diverging_condition_match() { + fn inner() { + match true { + false => false, + _ if return true => false, + true => false, + } + } + + assert!(inner()); +}