aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-12-01 17:08:46 -0800
committerGraydon Hoare <[email protected]>2010-12-01 17:09:02 -0800
commit98a63bd1f9fda47fc34b16d9f0782022e1022277 (patch)
tree25796c068e3219553a6b7e984d512523ddd754cf /src
parentrustc: Annotate variants with their types. This may be useful for trans! (diff)
downloadrust-98a63bd1f9fda47fc34b16d9f0782022e1022277.tar.xz
rust-98a63bd1f9fda47fc34b16d9f0782022e1022277.zip
Add code to fail on non-exhaustive alt matching. Fix all cases this picked up in rustc.
Diffstat (limited to 'src')
-rw-r--r--src/boot/me/trans.ml9
-rw-r--r--src/comp/front/parser.rs7
-rw-r--r--src/comp/middle/fold.rs20
-rw-r--r--src/comp/middle/resolve.rs1
-rw-r--r--src/comp/middle/trans.rs39
-rw-r--r--src/comp/middle/typeck.rs27
6 files changed, 89 insertions, 14 deletions
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index 58cccb99..34f4d81d 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -4895,7 +4895,14 @@ let trans_visitor
last_jump
in
let last_jumps = Array.map trans_arm at.Ast.alt_tag_arms in
- Array.iter patch last_jumps
+ if not (arr_exists
+ (fun _ arm -> (fst arm.node) = Ast.PAT_wild)
+ at.Ast.alt_tag_arms)
+ then
+ trans_cond_fail "non-exhaustive match failure"
+ (Array.to_list last_jumps)
+ else
+ Array.iter patch last_jumps
(* If we're about to drop a channel, synthesize an upcall_flush_chan.
* TODO: This should rather appear in a chan dtor when chans become
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index ede8c637..f8d3bf07 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -388,6 +388,7 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr {
es.node, ast.ann_none);
hi = es.span;
}
+ case (_) { /* fall through */ }
}
}
@@ -401,6 +402,7 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr {
ret @spanned(lo, hi,
ast.expr_lit(lit, ast.ann_none));
}
+ case (_) { /* fall through */ }
}
auto e = parse_expr(p);
hi = p.get_span();
@@ -590,6 +592,7 @@ impure fn parse_binops(parser p,
more = true;
}
}
+ case (_) { /* fall through */ }
}
}
}
@@ -711,6 +714,7 @@ impure fn parse_assign_expr(parser p) -> @ast.expr {
ret @spanned(lo, rhs.span,
ast.expr_assign(lhs, rhs, ast.ann_none));
}
+ case (_) { /* fall through */ }
}
ret lhs;
}
@@ -733,6 +737,7 @@ impure fn parse_if_expr(parser p) -> @ast.expr {
els = some(eblk);
hi = eblk.span;
}
+ case (_) { /* fall through */ }
}
ret @spanned(lo, hi, ast.expr_if(cond, thn, els, ast.ann_none));
}
@@ -1039,6 +1044,7 @@ fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ {
}
}
}
+ case (_) { /* fall through */ }
}
}
ret rec(stmts=stmts, expr=expr, index=index);
@@ -1211,7 +1217,6 @@ impure fn parse_mod_items(parser p, token.token term) -> ast._mod {
case (ast.item_tag(?id, ?variants, _, _)) {
index.insert(id, ast.mie_item(u));
-
let uint variant_idx = 0u;
for (ast.variant v in variants) {
index.insert(v.name, ast.mie_tag_variant(u, variant_idx));
diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs
index 48cb1e01..203b8fda 100644
--- a/src/comp/middle/fold.rs
+++ b/src/comp/middle/fold.rs
@@ -87,6 +87,10 @@ type ast_fold[ENV] =
@ast.lit, ann a) -> @expr) fold_expr_lit,
(fn(&ENV e, &span sp,
+ @ast.expr e, @ast.ty ty,
+ ann a) -> @expr) fold_expr_cast,
+
+ (fn(&ENV e, &span sp,
@expr cond, &block thn,
&option.t[block] els,
ann a) -> @expr) fold_expr_if,
@@ -296,11 +300,13 @@ fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl {
case (some[@ast.ty](?t)) {
ty_ = some[@ast.ty](fold_ty(env, fld, t));
}
+ case (_) { /* fall through */ }
}
alt (local.init) {
case (some[@ast.expr](?e)) {
init_ = some[@ast.expr](fold_expr(env, fld, e));
}
+ case (_) { /* fall through */ }
}
let @ast.local local_ = @rec(ty=ty_, init=init_ with *local);
ret fld.fold_decl_local(env_, d.span, local_);
@@ -405,6 +411,12 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
ret fld.fold_expr_lit(env_, e.span, lit, t);
}
+ case (ast.expr_cast(?e, ?t, ?at)) {
+ auto ee = fold_expr(env_, fld, e);
+ auto tt = fold_ty(env, fld, t);
+ ret fld.fold_expr_cast(env_, e.span, ee, tt, at);
+ }
+
case (ast.expr_if(?cnd, ?thn, ?els, ?t)) {
auto ccnd = fold_expr(env_, fld, cnd);
auto tthn = fold_block(env_, fld, thn);
@@ -413,6 +425,7 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
case (some[block](?b)) {
eels = some(fold_block(env_, fld, b));
}
+ case (_) { /* fall through */ }
}
ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eels, t);
}
@@ -492,6 +505,7 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt {
case (some[@expr](?e)) {
oee = some(fold_expr(env_, fld, e));
}
+ case (_) { /* fall through */ }
}
ret fld.fold_stmt_ret(env_, s.span, oee);
}
@@ -737,6 +751,11 @@ fn identity_fold_expr_lit[ENV](&ENV env, &span sp, @ast.lit lit,
ret @respan(sp, ast.expr_lit(lit, a));
}
+fn identity_fold_expr_cast[ENV](&ENV env, &span sp, @ast.expr e,
+ @ast.ty t, ann a) -> @expr {
+ ret @respan(sp, ast.expr_cast(e, t, a));
+}
+
fn identity_fold_expr_if[ENV](&ENV env, &span sp,
@expr cond, &block thn,
&option.t[block] els, ann a) -> @expr {
@@ -956,6 +975,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
fold_expr_binary = bind identity_fold_expr_binary[ENV](_,_,_,_,_,_),
fold_expr_unary = bind identity_fold_expr_unary[ENV](_,_,_,_,_),
fold_expr_lit = bind identity_fold_expr_lit[ENV](_,_,_,_),
+ fold_expr_cast = bind identity_fold_expr_cast[ENV](_,_,_,_,_),
fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_),
fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_),
fold_expr_do_while
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 2655a6c5..498596d6 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -113,6 +113,7 @@ fn lookup_name(&env e, ast.ident i) -> option.t[def] {
case (some[uint](?ix)) {
ret found_decl_stmt(b.node.stmts.(ix));
}
+ case (_) { /* fall through */ }
}
}
}
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index bc580166..89055578 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -295,6 +295,7 @@ fn type_of_inner(@crate_ctxt cx, @typeck.ty t) -> TypeRef {
case (ast.alias) {
t = T_ptr(t);
}
+ case (_) { /* fall through */ }
}
atys += t;
}
@@ -506,6 +507,17 @@ fn iter_structural_ty(@block_ctxt cx,
i += 1;
}
}
+ case (typeck.ty_rec(?fields)) {
+ let int i = 0;
+ for (typeck.field fld in fields) {
+ auto llfld = r.bcx.build.GEP(v, vec(C_int(0), C_int(i)));
+ r = f(r.bcx, llfld, fld.ty);
+ i += 1;
+ }
+ }
+ case (_) {
+ cx.fcx.ccx.sess.unimpl("type in iter_structural_ty");
+ }
// FIXME: handle records and tags when we support them.
}
ret r;
@@ -560,6 +572,7 @@ fn iter_sequence(@block_ctxt cx,
auto et = typeck.plain_ty(typeck.ty_machine(common.ty_u8));
ret iter_sequence_body(cx, v, et, f, false);
}
+ case (_) { fail; }
}
cx.fcx.ccx.sess.bug("bad type in trans.iter_sequence");
fail;
@@ -765,6 +778,7 @@ fn target_type(@crate_ctxt cx, @typeck.ty t) -> @typeck.ty {
auto tm = typeck.ty_machine(cx.sess.get_targ_cfg().uint_type);
ret @rec(struct=tm with *t);
}
+ case (_) { /* fall through */ }
}
ret t;
}
@@ -813,8 +827,10 @@ impure fn trans_unary(@block_ctxt cx, ast.unop op,
C_int(abi.box_rc_field_refcnt)));
ret res(sub.bcx, cx.build.Store(C_int(1), rc));
}
+ case (_) {
+ cx.fcx.ccx.sess.unimpl("expr variant in trans_unary");
+ }
}
- cx.fcx.ccx.sess.unimpl("expr variant in trans_unary");
fail;
}
@@ -859,6 +875,8 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op,
ret join_results(cx, T_bool(),
vec(lhs_true_res, rhs_res));
}
+
+ case (_) { /* fall through */ }
}
// Remaining cases are eager:
@@ -958,8 +976,11 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op,
sub.val = cx.build.ICmp(lib.llvm.LLVMIntSGT, lhs.val, sub.val);
ret sub;
}
+
+ case (_) {
+ cx.fcx.ccx.sess.unimpl("operator in trans_binary");
+ }
}
- cx.fcx.ccx.sess.unimpl("expr variant in trans_binary");
fail;
}
@@ -994,6 +1015,8 @@ fn join_results(@block_ctxt parent_cx,
// onward.
ret live.(0);
}
+
+ case (_) { /* fall through */ }
}
// We have >1 incoming edges. Make a join block and br+phi them into it.
@@ -1020,6 +1043,7 @@ impure fn trans_if(@block_ctxt cx, @ast.expr cond,
case (some[ast.block](?eblk)) {
else_res = trans_block(else_cx, eblk);
}
+ case (_) { /* fall through */ }
}
cond_res.bcx.build.CondBr(cond_res.val,
@@ -1119,8 +1143,8 @@ fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
auto v = r.bcx.build.GEP(r.val, vec(C_int(0), C_int(ix as int)));
ret tup(res(r.bcx, v), lv._1);
}
+ case (_) { cx.fcx.ccx.sess.unimpl("field variant in trans_field"); }
}
- cx.fcx.ccx.sess.unimpl("field variant in trans_field");
fail;
}
@@ -1132,8 +1156,8 @@ fn trans_lval(@block_ctxt cx, @ast.expr e) -> tup(result, bool) {
case (ast.expr_field(?base, ?ident, ?ann)) {
ret trans_field(cx, e.span, base, ident, ann);
}
+ case (_) { cx.fcx.ccx.sess.unimpl("expr variant in trans_lval"); }
}
- cx.fcx.ccx.sess.unimpl("expr variant in trans_lval");
fail;
}
@@ -1366,6 +1390,7 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
case (some[@ast.expr](?x)) {
r = trans_expr(cx, x);
}
+ case (_) { /* fall through */ }
}
// Run all cleanups and back out.
@@ -1388,6 +1413,7 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
r.val = r.bcx.build.Ret(r.val);
ret r;
}
+ case (_) { /* fall through */ }
}
// FIXME: until LLVM has a unit type, we are moving around
@@ -1426,6 +1452,7 @@ impure fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
copy_ty(sub.bcx, true, llptr, sub.val,
typeck.expr_ty(e));
}
+ case (_) { /* fall through */ }
}
}
}
@@ -1496,8 +1523,10 @@ iter block_locals(&ast.block b) -> @ast.local {
case (ast.decl_local(?local)) {
put local;
}
+ case (_) { /* fall through */ }
}
}
+ case (_) { /* fall through */ }
}
}
}
@@ -1626,6 +1655,7 @@ impure fn trans_item(@crate_ctxt cx, &ast.item item) {
auto sub_cx = @rec(path=cx.path + "." + name with *cx);
trans_mod(sub_cx, m);
}
+ case (_) { /* fall through */ }
}
}
@@ -1650,6 +1680,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
case (ast.item_mod(?name, ?m, ?mid)) {
cx.items.insert(mid, i);
}
+ case (_) { /* fall through */ }
}
ret cx;
}
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 80bafb29..79f57be2 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -537,13 +537,15 @@ fn mode_is_alias(ast.mode m) -> bool {
case (ast.val) { ret false; }
case (ast.alias) { ret true; }
}
+ fail;
}
fn type_is_nil(@ty t) -> bool {
alt (t.struct) {
case (ty_nil) { ret true; }
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn type_is_structural(@ty t) -> bool {
@@ -551,24 +553,27 @@ fn type_is_structural(@ty t) -> bool {
// FIXME: cover tag when we support it.
case (ty_tup(_)) { ret true; }
case (ty_rec(_)) { ret true; }
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn type_is_binding(@ty t) -> bool {
alt (t.struct) {
// FIXME: cover obj when we support it.
case (ty_fn(_,_)) { ret true; }
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn type_is_boxed(@ty t) -> bool {
alt (t.struct) {
case (ty_str) { ret true; }
case (ty_vec(_)) { ret true; }
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn type_is_scalar(@ty t) -> bool {
@@ -578,8 +583,9 @@ fn type_is_scalar(@ty t) -> bool {
case (ty_uint) { ret true; }
case (ty_machine(_)) { ret true; }
case (ty_char) { ret true; }
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn type_is_fp(@ty t) -> bool {
@@ -588,10 +594,12 @@ fn type_is_fp(@ty t) -> bool {
alt (tm) {
case (common.ty_f32) { ret true; }
case (common.ty_f64) { ret true; }
+ case (_) { ret false; }
}
}
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn type_is_signed(@ty t) -> bool {
@@ -603,10 +611,12 @@ fn type_is_signed(@ty t) -> bool {
case (common.ty_i16) { ret true; }
case (common.ty_i32) { ret true; }
case (common.ty_i64) { ret true; }
+ case (_) { ret false; }
}
}
+ case (_) { ret false; }
}
- ret false;
+ fail;
}
fn plain_ty(&sty st) -> @ty {
@@ -662,7 +672,6 @@ fn expr_ty(@ast.expr expr) -> @ty {
case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); }
case (ast.expr_name(_, _, ?ann)) { ret ann_to_type(ann); }
}
-
fail;
}
@@ -1198,6 +1207,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
case (ast.ne) { t = plain_ty(ty_bool); }
case (ast.ge) { t = plain_ty(ty_bool); }
case (ast.gt) { t = plain_ty(ty_bool); }
+ case (_) { /* fall through */ }
}
ret @fold.respan[ast.expr_](expr.span,
ast.expr_binary(binop, lhs_1, rhs_1,
@@ -1506,6 +1516,7 @@ fn check_stmt(&fn_ctxt fcx, &@ast.stmt stmt)
auto expr_1 = demand_expr(fcx, lty, expr_0);
init = some[@ast.expr](expr_1);
}
+ case (_) { /* fall through */ }
}
auto local_1 = @rec(init = init with *local);