about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-02-15 09:40:42 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-02-15 15:47:42 +0100
commit67cc89f38d2e75cb0dcd6303fbe4bb4f659277a7 (patch)
tree99caacd6c05c72beb28e73a9aa759b5db1d88114
parent4b63826050dfc579b9ac65a6b72ad0ca6f6b51fc (diff)
downloadrust-67cc89f38d2e75cb0dcd6303fbe4bb4f659277a7.tar.gz
rust-67cc89f38d2e75cb0dcd6303fbe4bb4f659277a7.zip
Rewrite exhaustiveness checker
Issue #352
Closes #1720

The old checker would happily accept things like 'alt x { @some(a) { a } }'.
It now properly descends into patterns, checks exhaustiveness of booleans,
and complains when number/string patterns aren't exhaustive.
-rw-r--r--src/comp/metadata/decoder.rs8
-rw-r--r--src/comp/metadata/tydecode.rs10
-rw-r--r--src/comp/middle/check_alt.rs189
-rw-r--r--src/comp/middle/lint.rs2
-rw-r--r--src/comp/syntax/print/pprust.rs2
-rw-r--r--src/compiletest/procsrv.rs2
-rw-r--r--src/libcore/bool.rs3
-rw-r--r--src/libcore/str.rs4
-rw-r--r--src/libstd/four.rs6
-rw-r--r--src/libstd/serialization.rs2
-rw-r--r--src/libstd/treemap.rs8
-rw-r--r--src/libstd/tri.rs4
-rw-r--r--src/test/compile-fail/missing-return2.rs2
-rw-r--r--src/test/compile-fail/non-exhaustive-match-nested.rs2
-rw-r--r--src/test/compile-fail/non-exhaustive-match.rs16
-rw-r--r--src/test/pretty/block-disambig.rs10
-rw-r--r--src/test/pretty/unary-op-disambig.rs4
-rw-r--r--src/test/run-fail/unwind-alt.rs2
-rw-r--r--src/test/run-pass/alt-bot-2.rs2
-rw-r--r--src/test/run-pass/alt-pattern-lit.rs2
-rw-r--r--src/test/run-pass/alt-range.rs2
-rw-r--r--src/test/run-pass/alt-str.rs6
-rw-r--r--src/test/run-pass/binary-minus-without-space.rs2
-rw-r--r--src/test/run-pass/expr-alt-box.rs7
-rw-r--r--src/test/run-pass/expr-alt-generic-box1.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic-box2.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic-unique1.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic-unique2.rs2
-rw-r--r--src/test/run-pass/expr-alt-generic.rs2
-rw-r--r--src/test/run-pass/expr-alt-struct.rs2
-rw-r--r--src/test/run-pass/expr-alt-unique.rs5
-rw-r--r--src/test/run-pass/unreachable-code.rs2
32 files changed, 192 insertions, 124 deletions
diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs
index 2a089ad14ad..867497f37fd 100644
--- a/src/comp/metadata/decoder.rs
+++ b/src/comp/metadata/decoder.rs
@@ -218,7 +218,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
     let fam_ch = item_family(item);
     let did = {crate: cnum, node: did_.node};
     // We treat references to enums as references to types.
-    alt fam_ch {
+    alt check fam_ch {
       'c' { ast::def_const(did) }
       'u' { ast::def_fn(did, ast::unsafe_fn) }
       'f' { ast::def_fn(did, ast::impure_fn) }
@@ -336,7 +336,7 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
           _ { tcx.sess.bug("get_iface_methods: id has non-function type");
         } };
         result += [{ident: name, tps: bounds, fty: fty,
-                    purity: alt item_family(mth) {
+                    purity: alt check item_family(mth) {
                       'u' { ast::unsafe_fn }
                       'f' { ast::impure_fn }
                       'p' { ast::pure_fn }
@@ -346,7 +346,7 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
 }
 
 fn family_has_type_params(fam_ch: char) -> bool {
-    alt fam_ch {
+    alt check fam_ch {
       'c' | 'T' | 'm' | 'n' { false }
       'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' { true }
     }
@@ -370,7 +370,7 @@ fn describe_def(items: ebml::doc, id: ast::def_id) -> str {
 }
 
 fn item_family_to_str(fam: char) -> str {
-    alt fam {
+    alt check fam {
       'c' { ret "const"; }
       'f' { ret "fn"; }
       'u' { ret "unsafe fn"; }
diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs
index be7afbe0437..c7d434b3c1c 100644
--- a/src/comp/metadata/tydecode.rs
+++ b/src/comp/metadata/tydecode.rs
@@ -177,7 +177,7 @@ fn parse_proto(c: char) -> ast::proto {
 }
 
 fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
-    alt next(st) {
+    alt check next(st) {
       'n' { ret ty::mk_nil(st.tcx); }
       'z' { ret ty::mk_bot(st.tcx); }
       'b' { ret ty::mk_bool(st.tcx); }
@@ -185,7 +185,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
       'u' { ret ty::mk_uint(st.tcx); }
       'l' { ret ty::mk_float(st.tcx); }
       'M' {
-        alt next(st) {
+        alt check next(st) {
           'b' { ret ty::mk_mach_uint(st.tcx, ast::ty_u8); }
           'w' { ret ty::mk_mach_uint(st.tcx, ast::ty_u16); }
           'l' { ret ty::mk_mach_uint(st.tcx, ast::ty_u32); }
@@ -269,7 +269,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
       'Y' { ret ty::mk_type(st.tcx); }
       'y' { ret ty::mk_send_type(st.tcx); }
       'C' {
-        let ck = alt next(st) {
+        let ck = alt check next(st) {
           '&' { ty::ck_block }
           '@' { ty::ck_box }
           '~' { ty::ck_uniq }
@@ -355,7 +355,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
     assert (next(st) == '[');
     let inputs: [ty::arg] = [];
     while peek(st) != ']' {
-        let mode = alt peek(st) {
+        let mode = alt check peek(st) {
           '&' { ast::by_mut_ref }
           '-' { ast::by_move }
           '+' { ast::by_copy }
@@ -405,7 +405,7 @@ fn parse_bounds_data(data: @[u8], start: uint,
 fn parse_bounds(st: @pstate, conv: conv_did) -> @[ty::param_bound] {
     let bounds = [];
     while true {
-        bounds += [alt next(st) {
+        bounds += [alt check next(st) {
           'S' { ty::bound_send }
           'C' { ty::bound_copy }
           'I' { ty::bound_iface(parse_ty(st, conv)) }
diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs
index 5e377e33226..e1bf34ce5e4 100644
--- a/src/comp/middle/check_alt.rs
+++ b/src/comp/middle/check_alt.rs
@@ -27,7 +27,7 @@ fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
         /* Check for exhaustiveness */
         if mode == alt_exhaustive {
             let arms = vec::concat(vec::filter_map(arms, unguarded_pat));
-            check_exhaustive(tcx, ex.span, expr_ty(tcx, scrut), arms);
+            check_exhaustive(tcx, ex.span, arms);
         }
       }
       _ { }
@@ -59,89 +59,136 @@ fn check_arms(tcx: ty::ctxt, arms: [arm]) {
     }
 }
 
+fn raw_pat(p: @pat) -> @pat {
+    alt p.node {
+      pat_ident(_, some(s)) { raw_pat(s) }
+      _ { p }
+    }
+}
+
 // Precondition: patterns have been normalized
 // (not checked statically yet)
-fn check_exhaustive(tcx: ty::ctxt, sp:span, scrut_ty:ty::t, pats:[@pat]) {
-    let represented : [def_id] = [];
-    /* Determine the type of the scrutinee */
-    /* If it's not an enum, exit (bailing out on checking non-enum alts
-       for now) */
-    /* Otherwise, get the list of variants and make sure each one is
-     represented. Then recurse on the columns. */
-
-    let ty_def_id = alt ty::get(scrut_ty).struct {
-            ty_enum(id, _) { id }
-            _ { ret; } };
+fn check_exhaustive(tcx: ty::ctxt, sp: span, pats: [@pat]) {
+    if pats.len() == 0u {
+        tcx.sess.span_err(sp, "non-exhaustive patterns");
+        ret;
+    }
+    // If there a non-refutable pattern in the set, we're okay.
+    for pat in pats { if !is_refutable(tcx, pat) { ret; } }
 
-    let variants = *enum_variants(tcx, ty_def_id);
-    for pat in pats {
-        if !is_refutable(tcx, pat) {
-                /* automatically makes this alt complete */ ret;
+    alt ty::get(ty::node_id_to_type(tcx, pats[0].id)).struct {
+      ty::ty_enum(id, _) {
+        check_exhaustive_enum(tcx, id, sp, pats);
+      }
+      ty::ty_box(_) {
+        check_exhaustive(tcx, sp, vec::filter_map(pats, {|p|
+            alt raw_pat(p).node { pat_box(sub) { some(sub) } _ { none } }
+        }));
+      }
+      ty::ty_uniq(_) {
+        check_exhaustive(tcx, sp, vec::filter_map(pats, {|p|
+            alt raw_pat(p).node { pat_uniq(sub) { some(sub) } _ { none } }
+        }));
+      }
+      ty::ty_tup(ts) {
+        let cols = vec::init_elt_mut(ts.len(), []);
+        for p in pats {
+            alt raw_pat(p).node {
+              pat_tup(sub) {
+                vec::iteri(sub) {|i, sp| cols[i] += [sp];}
+              }
+              _ {}
+            }
         }
-        alt pat.node {
-                // want the def_id for the constructor
-            pat_enum(id,_) {
-                alt tcx.def_map.find(pat.id) {
-                    some(def_variant(_, variant_def_id)) {
-                        represented += [variant_def_id];
+        vec::iter(cols) {|col| check_exhaustive(tcx, sp, col); }
+      }
+      ty::ty_rec(fs) {
+        let cols = vec::init_elt(fs.len(), {mutable wild: false,
+                                            mutable pats: []});
+        for p in pats {
+            alt raw_pat(p).node {
+              pat_rec(sub, _) {
+                vec::iteri(fs) {|i, field|
+                    alt vec::find(sub, {|pf| pf.ident == field.ident }) {
+                      some(pf) { cols[i].pats += [pf.pat]; }
+                      none { cols[i].wild = true; }
                     }
-                    _ { tcx.sess.span_bug(pat.span, "check_exhaustive:
-                          pat_tag not bound to a variant"); }
                 }
+              }
+              _ {}
+            }
+        }
+        vec::iter(cols) {|col|
+            if !col.wild { check_exhaustive(tcx, sp, copy col.pats); }
+        }
+      }
+      ty::ty_bool {
+        let saw_true = false, saw_false = false;
+        for p in pats {
+            alt raw_pat(p).node {
+              pat_lit(@{node: expr_lit(@{node: lit_bool(b), _}), _}) {
+                if b { saw_true = true; }
+                else { saw_false = true; }
+              }
+              _ {}
             }
-            _ { tcx.sess.span_bug(pat.span, "check_exhaustive: ill-typed \
-                  pattern");   // we know this has enum type,
-            }                  // so anything else should be impossible
-         }
-    }
-    fn not_represented(v: [def_id], &&vinfo: variant_info) -> bool {
-        !vec::contains(v, vinfo.id)
-    }
-    // Could be more efficient (bitvectors?)
-    alt vec::find(variants, bind not_represented(represented,_)) {
-        some(bad) {
-        // complain
-        // TODO: give examples of cases that aren't covered
-            tcx.sess.note("Patterns not covered include:");
-            tcx.sess.note(bad.name);
-            tcx.sess.span_err(sp, "Non-exhaustive pattern");
         }
-        _ {}
+        if !saw_true { tcx.sess.span_err(
+            sp, "non-exhaustive bool patterns: true not covered"); }
+        if !saw_false { tcx.sess.span_err(
+            sp, "non-exhaustive bool patterns: false not covered"); }
+      }
+      ty::ty_nil {
+        let seen = vec::any(pats, {|p|
+            alt raw_pat(p).node {
+              pat_lit(@{node: expr_lit(@{node: lit_nil, _}), _}) { true }
+              _ { false }
+            }
+        });
+        if !seen { tcx.sess.span_err(sp, "non-exhaustive patterns"); }
+      }
+      // Literal patterns are always considered non-exhaustive
+      _ {
+        tcx.sess.span_err(sp, "non-exhaustive literal patterns");
+      }
     }
-    // Otherwise, check subpatterns
-    // inefficient
-    for variant in variants {
-        // rows consists of the argument list for each pat that's an enum
-        let rows : [[@pat]] = [];
-        for pat in pats {
+}
+
+fn check_exhaustive_enum(tcx: ty::ctxt, enum_id: def_id, sp: span,
+                         pats: [@pat]) {
+    let variants = enum_variants(tcx, enum_id);
+    let columns_by_variant = vec::map(*variants, {|v|
+        {mutable seen: false,
+         cols: vec::init_elt_mut(v.args.len(), [])}
+    });
+
+    for pat in pats {
+        let pat = raw_pat(pat);
+        alt tcx.def_map.get(pat.id) {
+          def_variant(_, id) {
+            let variant_idx =
+                option::get(vec::position(*variants, {|v| v.id == id}));
+            columns_by_variant[variant_idx].seen = true;
             alt pat.node {
-               pat_enum(id, args) {
-                  alt tcx.def_map.find(pat.id) {
-                      some(def_variant(_,variant_id))
-                        if variant_id == variant.id { rows += [args]; }
-                      _ { }
-                  }
-               }
-               _ {}
+              pat_enum(_, args) {
+                vec::iteri(args) {|i, p|
+                    columns_by_variant[variant_idx].cols[i] += [p];
+                }
+              }
+              _ {}
             }
+          }
+          _ {}
         }
-        if check vec::is_not_empty(rows) {
-             let i = 0u;
-             for it in rows[0] {
-                let column = [it];
-                // Annoying -- see comment in
-                // tstate::states::find_pre_post_state_loop
-                check vec::is_not_empty(rows);
-                for row in vec::tail(rows) {
-                  column += [row[i]];
-                }
-                check_exhaustive(tcx, sp, pat_ty(tcx, it), column);
-                i += 1u;
-             }
+    }
+
+    vec::iteri(columns_by_variant) {|i, cv|
+        if !cv.seen {
+            tcx.sess.span_err(sp, "non-exhaustive patterns: variant `" +
+                              variants[i].name + "` not covered");
+        } else {
+            vec::iter(cv.cols) {|col| check_exhaustive(tcx, sp, col); }
         }
-        // This shouldn't actually happen, since there were no
-        // irrefutable patterns if we got here.
-        else { cont; }
     }
 }
 
diff --git a/src/comp/middle/lint.rs b/src/comp/middle/lint.rs
index ff1b97b9587..f46a50ea4a1 100644
--- a/src/comp/middle/lint.rs
+++ b/src/comp/middle/lint.rs
@@ -40,7 +40,7 @@ fn time(do_it: bool, what: str, thunk: fn()) {
 fn merge_opts(attrs: [ast::attribute], cmd_opts: [(option, bool)]) ->
     [(option, bool)] {
     fn str_to_option(name: str) -> (option, bool) {
-        ret alt name {
+        ret alt check name {
           "ctypes" { (ctypes, true) }
           "no_ctypes" { (ctypes, false) }
         }
diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs
index 9cd9cd0503a..23cea66e8db 100644
--- a/src/comp/syntax/print/pprust.rs
+++ b/src/comp/syntax/print/pprust.rs
@@ -1023,7 +1023,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
       }
       ast::expr_be(result) { word_nbsp(s, "be"); print_expr(s, result); }
       ast::expr_log(lvl, lexp, expr) {
-        alt lvl {
+        alt check lvl {
           1 { word_nbsp(s, "log"); print_expr(s, expr); }
           0 { word_nbsp(s, "log_err"); print_expr(s, expr); }
           2 {
diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs
index 9304e359321..b856b092e7a 100644
--- a/src/compiletest/procsrv.rs
+++ b/src/compiletest/procsrv.rs
@@ -68,7 +68,7 @@ fn run(lib_path: str, prog: str, args: [str],
     let count = 2;
     while count > 0 {
         let stream = comm::recv(p);
-        alt stream {
+        alt check stream {
             (1, s) {
                 outs = s;
             }
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
index d027e3825e1..cc4efe54dfc 100644
--- a/src/libcore/bool.rs
+++ b/src/libcore/bool.rs
@@ -60,9 +60,10 @@ pure fn is_false(v: t) -> bool { !v }
   brief = "Parse logic value from `s`"
 )]
 pure fn from_str(s: str) -> t {
-    alt s {
+    alt check s {
       "true" { true }
       "false" { false }
+      _ { fail "'" + s + "' is not a valid boolean string"; }
     }
 }
 
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index d71828c79e8..f79594a3023 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -2140,7 +2140,7 @@ mod tests {
     fn test_chars_iter() {
         let i = 0;
         chars_iter("x\u03c0y") {|ch|
-            alt i {
+            alt check i {
               0 { assert ch == 'x'; }
               1 { assert ch == '\u03c0'; }
               2 { assert ch == 'y'; }
@@ -2156,7 +2156,7 @@ mod tests {
         let i = 0;
 
         bytes_iter("xyz") {|bb|
-            alt i {
+            alt check i {
               0 { assert bb == 'x' as u8; }
               1 { assert bb == 'y' as u8; }
               2 { assert bb == 'z' as u8; }
diff --git a/src/libstd/four.rs b/src/libstd/four.rs
index ad44f225f25..e1804be2b91 100644
--- a/src/libstd/four.rs
+++ b/src/libstd/four.rs
@@ -166,7 +166,7 @@ Function: from_str
 Parse logic value from `s`
 */
 pure fn from_str(s: str) -> t {
-    alt s {
+    alt check s {
       "none" { none }
       "false" { four::false }
       "true" { four::true }
@@ -181,7 +181,7 @@ Convert `v` into a string
 */
 pure fn to_str(v: t) -> str {
     // FIXME replace with consts as soon as that works
-    alt v {
+    alt check v {
       0u8 { "none" }
       1u8 { "true" }
       2u8 { "false" }
@@ -265,7 +265,7 @@ mod tests {
     }
 
     fn to_tup(v: four::t) -> (bool, bool) {
-        alt v {
+        alt check v {
           0u8 { (false, false) }
           1u8 { (false, true) }
           2u8 { (true, false) }
diff --git a/src/libstd/serialization.rs b/src/libstd/serialization.rs
index 1b91b34fe11..1cc8cb529d8 100644
--- a/src/libstd/serialization.rs
+++ b/src/libstd/serialization.rs
@@ -241,7 +241,7 @@ fn test_option_int() {
     fn deserialize_0<S: deserializer>(s: S) -> option<int> {
         s.read_enum("option") {||
             s.read_enum_variant {|i|
-                alt i {
+                alt check i {
                   0u { none }
                   1u {
                     let v0 = s.read_enum_variant_arg(0u) {||
diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs
index bcea14df377..1647ea8f977 100644
--- a/src/libstd/treemap.rs
+++ b/src/libstd/treemap.rs
@@ -52,8 +52,12 @@ fn insert<K: copy, V: copy>(m: treemap<K, V>, k: K, v: V) {
         // We have to name left and right individually, because
         // otherwise the alias checker complains.
         if k < kk {
-            alt m { @node(_, _, left, _) { insert(left, k, v); } }
-        } else { alt m { @node(_, _, _, right) { insert(right, k, v); } } }
+            alt check m { @node(_, _, left, _) { insert(left, k, v); } }
+        } else {
+            alt check m {
+              @node(_, _, _, right) { insert(right, k, v); }
+            }
+        }
       }
     }
 }
diff --git a/src/libstd/tri.rs b/src/libstd/tri.rs
index 7cc749429ce..5835dbf8c42 100644
--- a/src/libstd/tri.rs
+++ b/src/libstd/tri.rs
@@ -137,7 +137,7 @@ Function: from_str
 Parse logic value from `s`
 */
 pure fn from_str(s: str) -> t {
-    alt s {
+    alt check s {
       "unknown" { unknown }
       "true" { tri::true }
       "false" { tri::false }
@@ -151,7 +151,7 @@ Convert `v` into a string
 */
 pure fn to_str(v: t) -> str {
     // FIXME replace with consts as soon as that works
-    alt v {
+    alt check v {
       0u8 { "unknown" }
       1u8 { "true" }
       2u8 { "false" }
diff --git a/src/test/compile-fail/missing-return2.rs b/src/test/compile-fail/missing-return2.rs
index 26a9febd3c7..54d8de63014 100644
--- a/src/test/compile-fail/missing-return2.rs
+++ b/src/test/compile-fail/missing-return2.rs
@@ -3,7 +3,7 @@
 fn f() -> int {
     // Make sure typestate doesn't interpret this alt expression
     // as the function result
-    alt true { true { } };
+    alt check true { true { } };
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/non-exhaustive-match-nested.rs b/src/test/compile-fail/non-exhaustive-match-nested.rs
index b3b854f53e5..a4efbb5684c 100644
--- a/src/test/compile-fail/non-exhaustive-match-nested.rs
+++ b/src/test/compile-fail/non-exhaustive-match-nested.rs
@@ -1,5 +1,5 @@
 // -*- rust -*-
-// error-pattern: Non-exhaustive pattern
+// error-pattern: non-exhaustive patterns
 enum t { a(u), b }
 enum u { c, d }
 
diff --git a/src/test/compile-fail/non-exhaustive-match.rs b/src/test/compile-fail/non-exhaustive-match.rs
index 7beb7f1b17d..b2fec6c0c5d 100644
--- a/src/test/compile-fail/non-exhaustive-match.rs
+++ b/src/test/compile-fail/non-exhaustive-match.rs
@@ -1,5 +1,15 @@
-// -*- rust -*-
-// error-pattern: Non-exhaustive pattern
 enum t { a, b, }
 
-fn main() { let x = a; alt x { b { } } }
+fn main() {
+    let x = a;
+    alt x { b { } } //! ERROR non-exhaustive patterns
+    alt true { //! ERROR non-exhaustive bool patterns
+      true {}
+    }
+    alt @some(10) { //! ERROR non-exhaustive patterns
+      @none {}
+    }
+    alt (2, 3, 4) { //! ERROR non-exhaustive literal patterns
+      (_, _, 4) {}
+    }
+}
diff --git a/src/test/pretty/block-disambig.rs b/src/test/pretty/block-disambig.rs
index d1a7a9b85ac..64752505952 100644
--- a/src/test/pretty/block-disambig.rs
+++ b/src/test/pretty/block-disambig.rs
@@ -8,7 +8,7 @@ fn test2() -> int { let val = @0; { } *val }
 
 fn test3() {
     let regs = @{mutable eax: 0};
-    alt true { true { } }
+    alt check true { true { } }
     (*regs).eax = 1;
 }
 
@@ -20,13 +20,13 @@ fn test6() -> bool { { } (true || false) && true }
 
 fn test7() -> uint {
     let regs = @0;
-    alt true { true { } }
+    alt check true { true { } }
     (*regs < 2) as uint
 }
 
 fn test8() -> int {
     let val = @0;
-    alt true {
+    alt check true {
         true { }
     }
     if *val < 1 {
@@ -36,11 +36,11 @@ fn test8() -> int {
     }
 }
 
-fn test9() { let regs = @mutable 0; alt true { true { } } *regs += 1; }
+fn test9() { let regs = @mutable 0; alt check true { true { } } *regs += 1; }
 
 fn test10() -> int {
     let regs = @mutable [0];
-    alt true { true { } }
+    alt check true { true { } }
     (*regs)[0]
 }
 
diff --git a/src/test/pretty/unary-op-disambig.rs b/src/test/pretty/unary-op-disambig.rs
index 88406813b42..e9fd2c2dc2c 100644
--- a/src/test/pretty/unary-op-disambig.rs
+++ b/src/test/pretty/unary-op-disambig.rs
@@ -10,8 +10,8 @@ fn if_semi() -> int { if true { f() } else { f() }; -1 }
 
 fn if_nosemi() -> int { (if true { 0 } else { 0 }) - 1 }
 
-fn alt_semi() -> int { alt true { true { f() } }; -1 }
+fn alt_semi() -> int { alt check true { true { f() } }; -1 }
 
-fn alt_no_semi() -> int { (alt true { true { 0 } }) - 1 }
+fn alt_no_semi() -> int { (alt check true { true { 0 } }) - 1 }
 
 fn stmt() { { f() }; -1; }
diff --git a/src/test/run-fail/unwind-alt.rs b/src/test/run-fail/unwind-alt.rs
index 741a7eb4975..1cd512cfc41 100644
--- a/src/test/run-fail/unwind-alt.rs
+++ b/src/test/run-fail/unwind-alt.rs
@@ -4,7 +4,7 @@ fn test_box() {
     @0;
 }
 fn test_str() {
-    let res = alt false { true { "happy" } };
+    let res = alt check false { true { "happy" } };
     assert res == "happy";
 }
 fn main() {
diff --git a/src/test/run-pass/alt-bot-2.rs b/src/test/run-pass/alt-bot-2.rs
index 3183b580fc6..e3fd606c2d8 100644
--- a/src/test/run-pass/alt-bot-2.rs
+++ b/src/test/run-pass/alt-bot-2.rs
@@ -1,3 +1,3 @@
 // n.b. This was only ever failing with optimization disabled.
-fn a() -> int { alt ret 1 { 2 { 3 } } }
+fn a() -> int { alt check ret 1 { 2 { 3 } } }
 fn main() { a(); }
diff --git a/src/test/run-pass/alt-pattern-lit.rs b/src/test/run-pass/alt-pattern-lit.rs
index afc72c80afa..d266a63418f 100644
--- a/src/test/run-pass/alt-pattern-lit.rs
+++ b/src/test/run-pass/alt-pattern-lit.rs
@@ -1,7 +1,7 @@
 
 
 fn altlit(f: int) -> int {
-    alt f {
+    alt check f {
       10 { #debug("case 10"); ret 20; }
       11 { #debug("case 11"); ret 22; }
     }
diff --git a/src/test/run-pass/alt-range.rs b/src/test/run-pass/alt-range.rs
index 1cd29cb3517..e85a82a2fd4 100644
--- a/src/test/run-pass/alt-range.rs
+++ b/src/test/run-pass/alt-range.rs
@@ -7,7 +7,7 @@ fn main() {
       6u to 7u { fail "shouldn't match range"; }
       _ {}
     }
-    alt 5u {
+    alt check 5u {
       1u { fail "should match non-first range"; }
       2u to 6u {}
     }
diff --git a/src/test/run-pass/alt-str.rs b/src/test/run-pass/alt-str.rs
index 6b7a3e6c279..c0a096cc2c9 100644
--- a/src/test/run-pass/alt-str.rs
+++ b/src/test/run-pass/alt-str.rs
@@ -1,7 +1,7 @@
 // Issue #53
 
 fn main() {
-    alt "test" { "not-test" { fail; } "test" { } _ { fail; } }
+    alt check "test" { "not-test" { fail; } "test" { } _ { fail; } }
 
     enum t { tag1(str), tag2, }
 
@@ -13,9 +13,9 @@ fn main() {
       _ { fail; }
     }
 
-    let x = alt "a" { "a" { 1 } "b" { 2 } };
+    let x = alt check "a" { "a" { 1 } "b" { 2 } };
     assert (x == 1);
 
-    alt "a" { "a" { } "b" { } }
+    alt check "a" { "a" { } "b" { } }
 
 }
diff --git a/src/test/run-pass/binary-minus-without-space.rs b/src/test/run-pass/binary-minus-without-space.rs
index cb31faacc3c..79627d5501d 100644
--- a/src/test/run-pass/binary-minus-without-space.rs
+++ b/src/test/run-pass/binary-minus-without-space.rs
@@ -1,6 +1,6 @@
 // Check that issue #954 stays fixed
 
 fn main() {
-    alt -1 { -1 {} }
+    alt check -1 { -1 {} }
     assert 1-1 == 0;
 }
diff --git a/src/test/run-pass/expr-alt-box.rs b/src/test/run-pass/expr-alt-box.rs
index 84c9e424f46..93a65d62977 100644
--- a/src/test/run-pass/expr-alt-box.rs
+++ b/src/test/run-pass/expr-alt-box.rs
@@ -4,10 +4,13 @@
 // -*- rust -*-
 
 // Tests for alt as expressions resulting in boxed types
-fn test_box() { let res = alt true { true { @100 } }; assert (*res == 100); }
+fn test_box() {
+    let res = alt check true { true { @100 } };
+    assert (*res == 100);
+}
 
 fn test_str() {
-    let res = alt true { true { "happy" } };
+    let res = alt check true { true { "happy" } };
     assert (res == "happy");
 }
 
diff --git a/src/test/run-pass/expr-alt-generic-box1.rs b/src/test/run-pass/expr-alt-generic-box1.rs
index 98f3b86aec9..bdaa676954b 100644
--- a/src/test/run-pass/expr-alt-generic-box1.rs
+++ b/src/test/run-pass/expr-alt-generic-box1.rs
@@ -5,7 +5,7 @@
 type compare<T> = fn@(@T, @T) -> bool;
 
 fn test_generic<T>(expected: @T, eq: compare<T>) {
-    let actual: @T = alt true { true { expected } };
+    let actual: @T = alt check true { true { expected } };
     assert (eq(expected, actual));
 }
 
diff --git a/src/test/run-pass/expr-alt-generic-box2.rs b/src/test/run-pass/expr-alt-generic-box2.rs
index b4a40c51361..de1143464c8 100644
--- a/src/test/run-pass/expr-alt-generic-box2.rs
+++ b/src/test/run-pass/expr-alt-generic-box2.rs
@@ -5,7 +5,7 @@
 type compare<T> = fn@(T, T) -> bool;
 
 fn test_generic<T: copy>(expected: T, eq: compare<T>) {
-    let actual: T = alt true { true { expected } };
+    let actual: T = alt check true { true { expected } };
     assert (eq(expected, actual));
 }
 
diff --git a/src/test/run-pass/expr-alt-generic-unique1.rs b/src/test/run-pass/expr-alt-generic-unique1.rs
index 2b8b9f53946..55e33263776 100644
--- a/src/test/run-pass/expr-alt-generic-unique1.rs
+++ b/src/test/run-pass/expr-alt-generic-unique1.rs
@@ -4,7 +4,7 @@
 type compare<T> = fn@(~T, ~T) -> bool;
 
 fn test_generic<T: copy>(expected: ~T, eq: compare<T>) {
-    let actual: ~T = alt true { true { expected } };
+    let actual: ~T = alt check true { true { expected } };
     assert (eq(expected, actual));
 }
 
diff --git a/src/test/run-pass/expr-alt-generic-unique2.rs b/src/test/run-pass/expr-alt-generic-unique2.rs
index 0a0dd1dd8d5..9dc580ed3b0 100644
--- a/src/test/run-pass/expr-alt-generic-unique2.rs
+++ b/src/test/run-pass/expr-alt-generic-unique2.rs
@@ -5,7 +5,7 @@
 type compare<T> = fn@(T, T) -> bool;
 
 fn test_generic<T: copy>(expected: T, eq: compare<T>) {
-    let actual: T = alt true { true { expected } };
+    let actual: T = alt check true { true { expected } };
     assert (eq(expected, actual));
 }
 
diff --git a/src/test/run-pass/expr-alt-generic.rs b/src/test/run-pass/expr-alt-generic.rs
index 13da160c73c..84324a00db7 100644
--- a/src/test/run-pass/expr-alt-generic.rs
+++ b/src/test/run-pass/expr-alt-generic.rs
@@ -5,7 +5,7 @@
 type compare<T> = fn@(T, T) -> bool;
 
 fn test_generic<T: copy>(expected: T, eq: compare<T>) {
-    let actual: T = alt true { true { expected } };
+    let actual: T = alt check true { true { expected } };
     assert (eq(expected, actual));
 }
 
diff --git a/src/test/run-pass/expr-alt-struct.rs b/src/test/run-pass/expr-alt-struct.rs
index def9b607afe..52ec91884f6 100644
--- a/src/test/run-pass/expr-alt-struct.rs
+++ b/src/test/run-pass/expr-alt-struct.rs
@@ -5,7 +5,7 @@
 
 // Tests for alt as expressions resulting in structural types
 fn test_rec() {
-    let rs = alt true { true { {i: 100} } };
+    let rs = alt check true { true { {i: 100} } };
     assert (rs == {i: 100});
 }
 
diff --git a/src/test/run-pass/expr-alt-unique.rs b/src/test/run-pass/expr-alt-unique.rs
index f83dae4e9fa..e3a55892955 100644
--- a/src/test/run-pass/expr-alt-unique.rs
+++ b/src/test/run-pass/expr-alt-unique.rs
@@ -4,6 +4,9 @@
 // -*- rust -*-
 
 // Tests for alt as expressions resulting in boxed types
-fn test_box() { let res = alt true { true { ~100 } }; assert (*res == 100); }
+fn test_box() {
+    let res = alt check true { true { ~100 } };
+    assert (*res == 100);
+}
 
 fn main() { test_box(); }
diff --git a/src/test/run-pass/unreachable-code.rs b/src/test/run-pass/unreachable-code.rs
index 2570e598b08..d5f896d36d3 100644
--- a/src/test/run-pass/unreachable-code.rs
+++ b/src/test/run-pass/unreachable-code.rs
@@ -30,7 +30,7 @@ fn log_cont() { do { log(error, cont); } while false }
 fn ret_ret() -> int { ret (ret 2) + 3; }
 
 fn ret_guard() {
-    alt 2 {
+    alt check 2 {
       x if (ret) { x; }
     }
 }