Skip to content

Commit a98ea4f

Browse files
committed
rustc: Run block cleanups on else if blocks
With the scheme used to translate 'else if' currently the if expression is translated in a new (else) scope context. If that if expression wants to result in a value that requires refcounting then it will need to drop the refcount in the cleanups of the else block.
1 parent e840a37 commit a98ea4f

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

src/comp/middle/trans.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3706,8 +3706,15 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
37063706
alt (els) {
37073707
case (some[@ast::expr](?elexpr)) {
37083708
alt (elexpr.node) {
3709-
case (ast::expr_if(_, _, _, _)) {
3710-
else_res = trans_expr(else_cx, elexpr);
3709+
case (ast::expr_if(?cond, ?thn, ?els, _)) {
3710+
else_res = trans_if(else_cx, cond, thn, els);
3711+
// The if expression may need to use the else context to
3712+
// drop the refcount of its result so we need to run the
3713+
// cleanups
3714+
auto bcx = else_res.bcx;
3715+
bcx = trans_block_cleanups(bcx,
3716+
find_scope_cx(bcx));
3717+
else_res = res(bcx, else_res.val);
37113718
}
37123719
case (ast::expr_block(?blk, _)) {
37133720
// Calling trans_block directly instead of trans_expr

src/test/run-pass/expr-elseif-ref.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// xfail-stage0
2+
3+
// Make sure we drop the refs of the temporaries needed to return the
4+
// values from the else if branch
5+
6+
fn main() {
7+
let vec[uint] y = [10u];
8+
auto x = if (false) {
9+
y
10+
} else if (true) {
11+
y
12+
} else {
13+
y
14+
};
15+
16+
assert y.(0) == 10u;
17+
}

0 commit comments

Comments
 (0)