about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-12-01 17:08:46 -0800
committerGraydon Hoare <graydon@mozilla.com>2010-12-01 17:09:02 -0800
commit98a63bd1f9fda47fc34b16d9f0782022e1022277 (patch)
tree25796c068e3219553a6b7e984d512523ddd754cf /src
parentfd600bad4666758088ec69a355a0dbd86bb11c22 (diff)
downloadrust-98a63bd1f9fda47fc34b16d9f0782022e1022277.tar.gz
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 58cccb9922c..34f4d81db04 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 ede8c63705d..f8d3bf0727c 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 48cb1e01674..203b8fdaf03 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 2655a6c5726..498596d6000 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 bc5801661c5..89055578d55 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 80bafb29938..79f57be2ae1 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);