Skip to content

Commit b62bf8c

Browse files
committed
rustc: Allow if expressions to fail
1 parent 6824f11 commit b62bf8c

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

src/comp/middle/trans.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3660,7 +3660,8 @@ fn join_results(&@block_ctxt parent_cx,
36603660
}
36613661

36623662
fn trans_if(&@block_ctxt cx, &@ast::expr cond,
3663-
&ast::block thn, &option::t[@ast::expr] els) -> result {
3663+
&ast::block thn, &option::t[@ast::expr] els,
3664+
&ast::ann ann) -> result {
36643665

36653666
auto cond_res = trans_expr(cx, cond);
36663667

@@ -3699,12 +3700,12 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
36993700
// If we have an else expression, then the entire
37003701
// if expression can have a non-nil type.
37013702
// FIXME: This isn't quite right, particularly re: dynamic types
3702-
auto expr_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, elexpr);
3703+
auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types,
3704+
ann);
37033705
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
37043706
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
37053707
} else {
3706-
expr_llty = type_of(else_res.bcx.fcx.lcx.ccx, elexpr.span,
3707-
expr_ty);
3708+
expr_llty = type_of(cx.fcx.lcx.ccx, elexpr.span, expr_ty);
37083709
if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, expr_ty)) {
37093710
expr_llty = T_ptr(expr_llty);
37103711
}
@@ -5392,8 +5393,8 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
53925393
ret trans_binary(cx, op, x, y);
53935394
}
53945395

5395-
case (ast::expr_if(?cond, ?thn, ?els, _)) {
5396-
ret trans_if(cx, cond, thn, els);
5396+
case (ast::expr_if(?cond, ?thn, ?els, ?ann)) {
5397+
ret trans_if(cx, cond, thn, els, ann);
53975398
}
53985399

53995400
case (ast::expr_for(?decl, ?seq, ?body, _)) {

src/comp/middle/typeck.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,12 +1331,19 @@ mod Pushdown {
13311331
case (ast::expr_if(?cond, ?then_0, ?else_0, ?ann)) {
13321332
auto t = Demand::autoderef(scx, e.span, expected,
13331333
ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
1334-
pushdown_block(scx, expected, then_0);
1334+
1335+
auto then_t = ty::block_ty(scx.fcx.ccx.tcx, then_0);
1336+
if (!ty::type_is_bot(scx.fcx.ccx.tcx, then_t)) {
1337+
pushdown_block(scx, expected, then_0);
1338+
}
13351339

13361340
alt (else_0) {
13371341
case (none[@ast::expr]) { /* no-op */ }
13381342
case (some[@ast::expr](?e_0)) {
1339-
pushdown_expr(scx, expected, e_0);
1343+
auto else_t = ty::expr_ty(scx.fcx.ccx.tcx, e_0);
1344+
if (!ty::type_is_bot(scx.fcx.ccx.tcx, else_t)) {
1345+
pushdown_expr(scx, expected, e_0);
1346+
}
13401347
}
13411348
}
13421349
write::ty_only_fixup(scx, ann.id, t);
@@ -2129,21 +2136,30 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
21292136
check_block(scx, thn);
21302137
auto thn_t = block_ty(scx.fcx.ccx.tcx, thn);
21312138

2132-
auto elsopt_t;
2139+
auto if_t;
21332140
alt (elsopt) {
21342141
case (some[@ast::expr](?els)) {
21352142
check_expr(scx, els);
2136-
Pushdown::pushdown_expr(scx, thn_t, els);
2137-
elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
2143+
auto elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
2144+
if (!ty::type_is_bot(scx.fcx.ccx.tcx, elsopt_t)) {
2145+
Pushdown::pushdown_expr(scx, thn_t, els);
2146+
if_t = elsopt_t;
2147+
} else if (!ty::type_is_bot(scx.fcx.ccx.tcx, thn_t)) {
2148+
if_t = thn_t;
2149+
} else {
2150+
if_t = ty::mk_nil(scx.fcx.ccx.tcx);
2151+
}
21382152
}
21392153
case (none[@ast::expr]) {
2140-
elsopt_t = ty::mk_nil(scx.fcx.ccx.tcx);
2154+
if_t = ty::mk_nil(scx.fcx.ccx.tcx);
21412155
}
21422156
}
21432157

2144-
Pushdown::pushdown_block(scx, elsopt_t, thn);
2158+
if (!ty::type_is_bot(scx.fcx.ccx.tcx, thn_t)) {
2159+
Pushdown::pushdown_block(scx, if_t, thn);
2160+
}
21452161

2146-
write::ty_only_fixup(scx, a.id, elsopt_t);
2162+
write::ty_only_fixup(scx, a.id, if_t);
21472163
}
21482164

21492165
case (ast::expr_for(?decl, ?seq, ?body, ?a)) {

src/test/run-fail/expr-if-fail.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// xfail-stage0
2+
// error-pattern:explicit failure
3+
4+
fn main() {
5+
auto x = if (false) {
6+
0
7+
} else if (true) {
8+
fail
9+
} else {
10+
10
11+
};
12+
}

src/test/run-pass/expr-if-fail.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// xfail-stage0
2+
3+
fn test_if_fail() {
4+
auto x = if (false) {
5+
fail
6+
} else {
7+
10
8+
};
9+
assert (x == 10);
10+
}
11+
12+
fn test_else_fail() {
13+
auto x = if (true) {
14+
10
15+
} else {
16+
fail
17+
};
18+
assert (x == 10);
19+
}
20+
21+
fn test_elseif_fail() {
22+
auto x = if (false) {
23+
0
24+
} else if (false) {
25+
fail
26+
} else {
27+
10
28+
};
29+
assert (x == 10);
30+
}
31+
32+
fn main() {
33+
test_if_fail();
34+
test_else_fail();
35+
test_elseif_fail();
36+
}

0 commit comments

Comments
 (0)