rustc: Allow if expressions to fail
This commit is contained in:
parent
6824f119fc
commit
b62bf8cede
4 changed files with 79 additions and 14 deletions
|
@ -3660,7 +3660,8 @@ fn join_results(&@block_ctxt parent_cx,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_if(&@block_ctxt cx, &@ast::expr cond,
|
fn trans_if(&@block_ctxt cx, &@ast::expr cond,
|
||||||
&ast::block thn, &option::t[@ast::expr] els) -> result {
|
&ast::block thn, &option::t[@ast::expr] els,
|
||||||
|
&ast::ann ann) -> result {
|
||||||
|
|
||||||
auto cond_res = trans_expr(cx, cond);
|
auto cond_res = trans_expr(cx, cond);
|
||||||
|
|
||||||
|
@ -3699,12 +3700,12 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
|
||||||
// If we have an else expression, then the entire
|
// If we have an else expression, then the entire
|
||||||
// if expression can have a non-nil type.
|
// if expression can have a non-nil type.
|
||||||
// FIXME: This isn't quite right, particularly re: dynamic types
|
// FIXME: This isn't quite right, particularly re: dynamic types
|
||||||
auto expr_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, elexpr);
|
auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types,
|
||||||
|
ann);
|
||||||
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
||||||
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
|
expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
|
||||||
} else {
|
} else {
|
||||||
expr_llty = type_of(else_res.bcx.fcx.lcx.ccx, elexpr.span,
|
expr_llty = type_of(cx.fcx.lcx.ccx, elexpr.span, expr_ty);
|
||||||
expr_ty);
|
|
||||||
if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, expr_ty)) {
|
||||||
expr_llty = T_ptr(expr_llty);
|
expr_llty = T_ptr(expr_llty);
|
||||||
}
|
}
|
||||||
|
@ -5392,8 +5393,8 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
|
||||||
ret trans_binary(cx, op, x, y);
|
ret trans_binary(cx, op, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ast::expr_if(?cond, ?thn, ?els, _)) {
|
case (ast::expr_if(?cond, ?thn, ?els, ?ann)) {
|
||||||
ret trans_if(cx, cond, thn, els);
|
ret trans_if(cx, cond, thn, els, ann);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ast::expr_for(?decl, ?seq, ?body, _)) {
|
case (ast::expr_for(?decl, ?seq, ?body, _)) {
|
||||||
|
|
|
@ -1331,14 +1331,21 @@ mod Pushdown {
|
||||||
case (ast::expr_if(?cond, ?then_0, ?else_0, ?ann)) {
|
case (ast::expr_if(?cond, ?then_0, ?else_0, ?ann)) {
|
||||||
auto t = Demand::autoderef(scx, e.span, expected,
|
auto t = Demand::autoderef(scx, e.span, expected,
|
||||||
ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
|
ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
|
||||||
|
|
||||||
|
auto then_t = ty::block_ty(scx.fcx.ccx.tcx, then_0);
|
||||||
|
if (!ty::type_is_bot(scx.fcx.ccx.tcx, then_t)) {
|
||||||
pushdown_block(scx, expected, then_0);
|
pushdown_block(scx, expected, then_0);
|
||||||
|
}
|
||||||
|
|
||||||
alt (else_0) {
|
alt (else_0) {
|
||||||
case (none[@ast::expr]) { /* no-op */ }
|
case (none[@ast::expr]) { /* no-op */ }
|
||||||
case (some[@ast::expr](?e_0)) {
|
case (some[@ast::expr](?e_0)) {
|
||||||
|
auto else_t = ty::expr_ty(scx.fcx.ccx.tcx, e_0);
|
||||||
|
if (!ty::type_is_bot(scx.fcx.ccx.tcx, else_t)) {
|
||||||
pushdown_expr(scx, expected, e_0);
|
pushdown_expr(scx, expected, e_0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
write::ty_only_fixup(scx, ann.id, t);
|
write::ty_only_fixup(scx, ann.id, t);
|
||||||
}
|
}
|
||||||
case (ast::expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
case (ast::expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
||||||
|
@ -2129,21 +2136,30 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
|
||||||
check_block(scx, thn);
|
check_block(scx, thn);
|
||||||
auto thn_t = block_ty(scx.fcx.ccx.tcx, thn);
|
auto thn_t = block_ty(scx.fcx.ccx.tcx, thn);
|
||||||
|
|
||||||
auto elsopt_t;
|
auto if_t;
|
||||||
alt (elsopt) {
|
alt (elsopt) {
|
||||||
case (some[@ast::expr](?els)) {
|
case (some[@ast::expr](?els)) {
|
||||||
check_expr(scx, els);
|
check_expr(scx, els);
|
||||||
|
auto elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
|
||||||
|
if (!ty::type_is_bot(scx.fcx.ccx.tcx, elsopt_t)) {
|
||||||
Pushdown::pushdown_expr(scx, thn_t, els);
|
Pushdown::pushdown_expr(scx, thn_t, els);
|
||||||
elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
|
if_t = elsopt_t;
|
||||||
|
} else if (!ty::type_is_bot(scx.fcx.ccx.tcx, thn_t)) {
|
||||||
|
if_t = thn_t;
|
||||||
|
} else {
|
||||||
|
if_t = ty::mk_nil(scx.fcx.ccx.tcx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case (none[@ast::expr]) {
|
case (none[@ast::expr]) {
|
||||||
elsopt_t = ty::mk_nil(scx.fcx.ccx.tcx);
|
if_t = ty::mk_nil(scx.fcx.ccx.tcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pushdown::pushdown_block(scx, elsopt_t, thn);
|
if (!ty::type_is_bot(scx.fcx.ccx.tcx, thn_t)) {
|
||||||
|
Pushdown::pushdown_block(scx, if_t, thn);
|
||||||
|
}
|
||||||
|
|
||||||
write::ty_only_fixup(scx, a.id, elsopt_t);
|
write::ty_only_fixup(scx, a.id, if_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
case (ast::expr_for(?decl, ?seq, ?body, ?a)) {
|
case (ast::expr_for(?decl, ?seq, ?body, ?a)) {
|
||||||
|
|
12
src/test/run-fail/expr-if-fail.rs
Normal file
12
src/test/run-fail/expr-if-fail.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// xfail-stage0
|
||||||
|
// error-pattern:explicit failure
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
auto x = if (false) {
|
||||||
|
0
|
||||||
|
} else if (true) {
|
||||||
|
fail
|
||||||
|
} else {
|
||||||
|
10
|
||||||
|
};
|
||||||
|
}
|
36
src/test/run-pass/expr-if-fail.rs
Normal file
36
src/test/run-pass/expr-if-fail.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// xfail-stage0
|
||||||
|
|
||||||
|
fn test_if_fail() {
|
||||||
|
auto x = if (false) {
|
||||||
|
fail
|
||||||
|
} else {
|
||||||
|
10
|
||||||
|
};
|
||||||
|
assert (x == 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_else_fail() {
|
||||||
|
auto x = if (true) {
|
||||||
|
10
|
||||||
|
} else {
|
||||||
|
fail
|
||||||
|
};
|
||||||
|
assert (x == 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_elseif_fail() {
|
||||||
|
auto x = if (false) {
|
||||||
|
0
|
||||||
|
} else if (false) {
|
||||||
|
fail
|
||||||
|
} else {
|
||||||
|
10
|
||||||
|
};
|
||||||
|
assert (x == 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
test_if_fail();
|
||||||
|
test_else_fail();
|
||||||
|
test_elseif_fail();
|
||||||
|
}
|
Loading…
Reference in a new issue