about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-01-30 21:00:57 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-01-31 10:08:24 -0800
commitfba35e1a3c87892823d1f4d436b9f00a7864cf16 (patch)
tree1fadaaee99ef266bd2f709fb2aa5577184ab611e /src/comp
parent813a55d89135efb716dd80e96453a091a7cfc631 (diff)
downloadrust-fba35e1a3c87892823d1f4d436b9f00a7864cf16.tar.gz
rust-fba35e1a3c87892823d1f4d436b9f00a7864cf16.zip
Require alts to be exhaustive
middle::check_alt does the work. Lots of changes to add default cases
into alts that were previously inexhaustive.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/rpath.rs29
-rw-r--r--src/comp/driver/driver.rs4
-rw-r--r--src/comp/driver/session.rs2
-rw-r--r--src/comp/metadata/decoder.rs5
-rw-r--r--src/comp/metadata/encoder.rs3
-rw-r--r--src/comp/metadata/tyencode.rs5
-rw-r--r--src/comp/middle/alias.rs17
-rw-r--r--src/comp/middle/ast_map.rs52
-rw-r--r--src/comp/middle/check_alt.rs115
-rw-r--r--src/comp/middle/debuginfo.rs57
-rw-r--r--src/comp/middle/gc.rs12
-rw-r--r--src/comp/middle/kind.rs4
-rw-r--r--src/comp/middle/last_use.rs6
-rw-r--r--src/comp/middle/lint.rs1
-rw-r--r--src/comp/middle/mut.rs6
-rw-r--r--src/comp/middle/pat_util.rs16
-rw-r--r--src/comp/middle/resolve.rs128
-rw-r--r--src/comp/middle/shape.rs12
-rw-r--r--src/comp/middle/trans/alt.rs33
-rw-r--r--src/comp/middle/trans/base.rs179
-rw-r--r--src/comp/middle/trans/closure.rs4
-rw-r--r--src/comp/middle/trans/common.rs3
-rw-r--r--src/comp/middle/trans/impl.rs23
-rw-r--r--src/comp/middle/trans/tvec.rs7
-rw-r--r--src/comp/middle/trans/uniq.rs1
-rw-r--r--src/comp/middle/tstate/auxiliary.rs20
-rw-r--r--src/comp/middle/tstate/collect_locals.rs12
-rw-r--r--src/comp/middle/tstate/pre_post_conditions.rs45
-rw-r--r--src/comp/middle/tstate/states.rs9
-rw-r--r--src/comp/middle/ty.rs55
-rw-r--r--src/comp/middle/typeck.rs59
-rw-r--r--src/comp/syntax/ast.rs4
-rw-r--r--src/comp/syntax/ast_util.rs35
-rw-r--r--src/comp/syntax/ext/simplext.rs13
-rw-r--r--src/comp/syntax/parse/parser.rs19
-rw-r--r--src/comp/syntax/print/pprust.rs33
-rw-r--r--src/comp/syntax/visit.rs1
-rw-r--r--src/comp/util/ppaux.rs4
38 files changed, 689 insertions, 344 deletions
diff --git a/src/comp/back/rpath.rs b/src/comp/back/rpath.rs
index b848ca94590..a2030e10fab 100644
--- a/src/comp/back/rpath.rs
+++ b/src/comp/back/rpath.rs
@@ -11,6 +11,13 @@ import util::filesearch;
 
 export get_rpath_flags;
 
+pure fn not_win32(os: session::os) -> bool {
+  alt os {
+      session::os_win32 { false }
+      _ { true }
+  }
+}
+
 fn get_rpath_flags(sess: session::session, out_filename: str) -> [str] {
     let os = sess.targ_cfg.os;
 
@@ -99,12 +106,13 @@ fn get_rpaths_relative_to_output(os: session::os,
 fn get_rpath_relative_to_output(os: session::os,
                                 cwd: fs::path,
                                 output: fs::path,
-                                &&lib: fs::path) -> str {
+                                &&lib: fs::path) : not_win32(os) -> str {
     // Mac doesn't appear to support $ORIGIN
     let prefix = alt os {
         session::os_linux { "$ORIGIN" + fs::path_sep() }
         session::os_freebsd { "$ORIGIN" + fs::path_sep() }
         session::os_macos { "@executable_path" + fs::path_sep() }
+        session::os_win32 { std::util::unreachable(); }
     };
 
     prefix + get_relative_to(
@@ -309,24 +317,31 @@ mod test {
     #[test]
     #[cfg(target_os = "linux")]
     fn test_rpath_relative() {
-        let res = get_rpath_relative_to_output(session::os_linux,
+      let o = session::os_linux;
+      check not_win32(o);
+      let res = get_rpath_relative_to_output(o,
             "/usr", "bin/rustc", "lib/libstd.so");
-        assert res == "$ORIGIN/../lib";
+      assert res == "$ORIGIN/../lib";
     }
 
     #[test]
     #[cfg(target_os = "freebsd")]
     fn test_rpath_relative() {
-        let res = get_rpath_relative_to_output(session::os_freebsd,
+      let o = session::os_freebsd;
+      check not_win32(o);
+      let res = get_rpath_relative_to_output(o,
             "/usr", "bin/rustc", "lib/libstd.so");
-        assert res == "$ORIGIN/../lib";
+      assert res == "$ORIGIN/../lib";
     }
 
     #[test]
     #[cfg(target_os = "macos")]
     fn test_rpath_relative() {
-        let res = get_rpath_relative_to_output(session::os_macos,
-            "/usr", "bin/rustc", "lib/libstd.so");
+      // this is why refinements would be nice
+      let o = session::os_macos;
+      check not_win32(o);
+      let res = get_rpath_relative_to_output(o, "/usr", "bin/rustc",
+                                             "lib/libstd.so");
         assert res == "@executable_path/../lib";
     }
 
diff --git a/src/comp/driver/driver.rs b/src/comp/driver/driver.rs
index 78ec0330dd9..ac6d785e8b5 100644
--- a/src/comp/driver/driver.rs
+++ b/src/comp/driver/driver.rs
@@ -608,6 +608,8 @@ mod test {
         let match =
             alt getopts::getopts(["--test"], opts()) {
               ok(m) { m }
+              err(f) { fail "test_switch_implies_cfg_test: " +
+                       getopts::fail_str(f); }
             };
         let sessopts = build_session_options(match, diagnostic::emit);
         let sess = build_session(sessopts, "", diagnostic::emit);
@@ -622,6 +624,8 @@ mod test {
         let match =
             alt getopts::getopts(["--test", "--cfg=test"], opts()) {
               ok(m) { m }
+              err(f) { fail "test_switch_implies_cfg_test_unless_cfg_test: " +
+                       getopts::fail_str(f); }
             };
         let sessopts = build_session_options(match, diagnostic::emit);
         let sess = build_session(sessopts, "", diagnostic::emit);
diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs
index b570744a665..81f1c76a2c9 100644
--- a/src/comp/driver/session.rs
+++ b/src/comp/driver/session.rs
@@ -58,7 +58,7 @@ type session = @{targ_cfg: @config,
                  parse_sess: parse_sess,
                  codemap: codemap::codemap,
                  // For a library crate, this is always none
-                 mutable main_fn: option::t<node_id>,
+                 mutable main_fn: option::t<(node_id, codemap::span)>,
                  span_diagnostic: diagnostic::span_handler,
                  filesearch: filesearch::filesearch,
                  mutable building_library: bool,
diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs
index 266167affd4..8fb12aae533 100644
--- a/src/comp/metadata/decoder.rs
+++ b/src/comp/metadata/decoder.rs
@@ -3,6 +3,7 @@
 import std::{ebml, map, io};
 import io::writer_util;
 import syntax::{ast, ast_util};
+import driver::session::session;
 import front::attr;
 import middle::ty;
 import common::*;
@@ -302,7 +303,9 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
         let bounds = item_ty_param_bounds(mth, tcx, cdata);
         let name = item_name(mth);
         let ty = doc_type(mth, tcx, cdata);
-        let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f } };
+        let fty = alt ty::struct(tcx, ty) { ty::ty_fn(f) { f }
+          _ { tcx.sess.bug("get_iface_methods: id has non-function type");
+        } };
         result += [{ident: name, tps: bounds, fty: fty}];
     }
     @result
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
index bcd760b5c61..d4cdb7587bf 100644
--- a/src/comp/metadata/encoder.rs
+++ b/src/comp/metadata/encoder.rs
@@ -10,6 +10,7 @@ import middle::trans::common::crate_ctxt;
 import middle::ty;
 import middle::ty::node_id_to_type;
 import front::attr;
+import driver::session::session;
 
 export encode_metadata;
 export encoded_ty;
@@ -275,6 +276,8 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
             }
         }
       }
+      _ { ecx.ccx.tcx.sess.bug("encode_info_for_mod: \
+             undocumented invariant"); }
     }
     ebml::end_tag(ebml_w);
 }
diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs
index 5f78f305d8d..f116bb7e17f 100644
--- a/src/comp/metadata/tyencode.rs
+++ b/src/comp/metadata/tyencode.rs
@@ -5,6 +5,7 @@ import io::writer_util;
 import std::map::hashmap;
 import option::{some, none};
 import syntax::ast::*;
+import driver::session::session;
 import middle::ty;
 import syntax::print::pprust::*;
 
@@ -213,6 +214,10 @@ fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
           by_copy { w.write_char('+'); }
           by_ref { w.write_char('='); }
           by_val { w.write_char('#'); }
+          // tediously, this has to be there until there's a way
+          // to constraint post-typeck types not to contain a mode_infer
+          mode_infer { cx.tcx.sess.bug("enc_ty_fn: shouldn't see \
+            mode_infer"); }
         }
         enc_ty(w, cx, arg.ty);
     }
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs
index 0d4ecee7dea..98cade0ca26 100644
--- a/src/comp/middle/alias.rs
+++ b/src/comp/middle/alias.rs
@@ -6,10 +6,12 @@ import syntax::visit;
 import visit::vt;
 import core::{vec, option};
 import std::list;
+import std::util::unreachable;
 import option::{some, none, is_none};
 import list::list;
 import driver::session::session;
 import pat_util::*;
+import util::ppaux::ty_to_str;
 
 // This is not an alias-analyser (though it would merit from becoming one, or
 // getting input from one, to be more precise). It is a pass that checks
@@ -575,6 +577,11 @@ fn copy_is_expensive(tcx: ty::ctxt, ty: ty::t) -> bool {
             for f in fs { sum += score_ty(tcx, f.mt.ty); }
             sum
           }
+          _ {
+            tcx.sess.warn(#fmt("score_ty: unexpected type %s",
+               ty_to_str(tcx, ty)));
+            1u // ???
+          }
         };
     }
     ret score_ty(tcx, ty) > 8u;
@@ -611,6 +618,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
             let ty = ty::node_id_to_type(tcx, pat.id);
             let m = alt ty::struct(tcx, ty) {
               ty::ty_box(mt) { mt.mut != ast::imm }
+              _ { tcx.sess.span_bug(pat.span, "box pat has non-box type"); }
             },
                 c = if m  {some(contains(ty)) } else { mut };
             walk(tcx, c, p, set);
@@ -619,6 +627,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
             let ty = ty::node_id_to_type(tcx, pat.id);
             let m = alt ty::struct(tcx, ty) {
               ty::ty_uniq(mt) { mt.mut != ast::imm }
+              _ { tcx.sess.span_bug(pat.span, "uniq pat has non-uniq type"); }
             },
                 c = if m { some(contains(ty)) } else { mut };
             walk(tcx, c, p, set);
@@ -672,6 +681,10 @@ fn append_invalid(dest: list<@invalid>, src: list<@invalid>,
             }
             cur = *tail;
           }
+          list::nil {
+              fail "append_invalid: stop doesn't appear to be \
+                 a postfix of src";
+          }
         }
     }
     ret dest;
@@ -686,6 +699,10 @@ fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> {
             if !is_none(p) { out = list::cons(head, @out); }
             cur = *tail;
           }
+          list::nil {
+            // typestate would help...
+            unreachable();
+          }
         }
     }
     ret out;
diff --git a/src/comp/middle/ast_map.rs b/src/comp/middle/ast_map.rs
index 58c6bfc2914..97881ca17a2 100644
--- a/src/comp/middle/ast_map.rs
+++ b/src/comp/middle/ast_map.rs
@@ -44,15 +44,15 @@ fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk,
 }
 
 fn map_local(cx: ctx, loc: @local) {
-    pat_util::pat_bindings(loc.node.pat) {|p|
-        cx.map.insert(p.id, node_local(cx.local_id));
+    pat_util::pat_bindings(loc.node.pat) {|p_id, _s, _p|
+        cx.map.insert(p_id, node_local(cx.local_id));
         cx.local_id += 1u;
     };
 }
 
 fn map_arm(cx: ctx, arm: arm) {
-    pat_util::pat_bindings(arm.pats[0]) {|p|
-        cx.map.insert(p.id, node_local(cx.local_id));
+    pat_util::pat_bindings(arm.pats[0]) {|p_id, _s, _p|
+        cx.map.insert(p_id, node_local(cx.local_id));
         cx.local_id += 1u;
     };
 }
@@ -79,50 +79,6 @@ fn map_expr(cx: ctx, ex: @expr) {
     cx.map.insert(ex.id, node_expr(ex));
 }
 
-fn node_span(node: ast_node) -> codemap::span {
-    alt node {
-      node_item(item) { item.span }
-      node_native_item(nitem) { nitem.span }
-      node_expr(expr) { expr.span }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    import syntax::ast_util;
-
-    #[test]
-    fn test_node_span_item() {
-        let expected: codemap::span = ast_util::mk_sp(20u, 30u);
-        let node =
-            node_item(@{ident: "test",
-                        attrs: [],
-                        id: 0,
-                        node: item_mod({view_items: [], items: []}),
-                        span: expected});
-        assert (node_span(node) == expected);
-    }
-
-    #[test]
-    fn test_node_span_native_item() {
-        let expected: codemap::span = ast_util::mk_sp(20u, 30u);
-        let node =
-            node_native_item(@{ident: "test",
-                               attrs: [],
-                               node: native_item_ty,
-                               id: 0,
-                               span: expected});
-        assert (node_span(node) == expected);
-    }
-
-    #[test]
-    fn test_node_span_expr() {
-        let expected: codemap::span = ast_util::mk_sp(20u, 30u);
-        let node = node_expr(@{id: 0, node: expr_break, span: expected});
-        assert (node_span(node) == expected);
-    }
-}
-
 // Local Variables:
 // mode: rust
 // fill-column: 78;
diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs
index e78b9ddb77f..2577ed03a93 100644
--- a/src/comp/middle/check_alt.rs
+++ b/src/comp/middle/check_alt.rs
@@ -1,10 +1,14 @@
+
 import syntax::ast::*;
 import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
-                          lit_expr_eq};
+        lit_expr_eq, unguarded_pat};
+import syntax::codemap::span;
 import pat_util::*;
 import syntax::visit;
 import option::{some, none};
 import driver::session::session;
+import middle::ty;
+import middle::ty::*;
 
 fn check_crate(tcx: ty::ctxt, crate: @crate) {
     let v =
@@ -18,15 +22,20 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
 fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
     visit::visit_expr(ex, s, v);
     alt ex.node {
-        expr_alt(_, arms) {
-            check_arms(tcx, pat_util::normalize_arms(tcx, arms));
+        expr_alt(scrut, arms) {
+            check_arms(tcx, ex.span, scrut,
+                       pat_util::normalize_arms(tcx, arms));
         }
         _ { }
     }
 }
 
-fn check_arms(tcx: ty::ctxt, arms: [arm]) {
+fn check_arms(tcx: ty::ctxt, sp:span, scrut: @expr, arms: [arm]) {
     let i = 0;
+    let scrut_ty = expr_ty(tcx, scrut);
+    /* (Could both checks be done in a single pass?) */
+
+    /* Check for unreachable patterns */
     for arm: arm in arms {
         for arm_pat: @pat in arm.pats {
             let reachable = true;
@@ -47,6 +56,97 @@ fn check_arms(tcx: ty::ctxt, arms: [arm]) {
         }
         i += 1;
     }
+
+    /* Check for exhaustiveness */
+
+    check_exhaustive(tcx, sp, scrut_ty,
+       vec::concat(vec::filter_map(arms, unguarded_pat)));
+}
+
+// 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::struct(tcx, scrut_ty) {
+            ty_enum(id, _) { id }
+            _ { 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 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];
+                    }
+                    _ { tcx.sess.span_bug(pat.span, "check_exhaustive:
+                          pat_tag not bound to a variant"); }
+                }
+            }
+            _ { 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::member(vinfo.id, v)
+    }
+    // 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");
+        }
+        _ {}
+    }
+    // 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 {
+            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]; }
+                      _ { }
+                  }
+               }
+               _ {}
+            }
+        }
+        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;
+             }
+        }
+        // This shouldn't actually happen, since there were no
+        // irrefutable patterns if we got here.
+        else { cont; }
+    }
 }
 
 fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
@@ -145,8 +245,8 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
       pat_wild | pat_ident(_, none) { false }
       pat_lit(_) { true }
       pat_rec(fields, _) {
-        for field: field_pat in fields {
-            if is_refutable(tcx, field.pat) { ret true; }
+        for it: field_pat in fields {
+            if is_refutable(tcx, it.pat) { ret true; }
         }
         false
       }
@@ -156,10 +256,11 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
       }
       pat_enum(_, args) {
         let vdef = variant_def_ids(tcx.def_map.get(pat.id));
-        if vec::len(*ty::enum_variants(tcx, vdef.tg)) != 1u { ret true; }
+        if vec::len(*ty::enum_variants(tcx, vdef.enm)) != 1u { ret true; }
         for p: @pat in args { if is_refutable(tcx, p) { ret true; } }
         false
       }
+      pat_range(_, _) { true }
     }
 }
 
diff --git a/src/comp/middle/debuginfo.rs b/src/comp/middle/debuginfo.rs
index c16dedc1bd4..fe843c6795b 100644
--- a/src/comp/middle/debuginfo.rs
+++ b/src/comp/middle/debuginfo.rs
@@ -12,6 +12,7 @@ import codemap::span;
 import ast::ty;
 import pat_util::*;
 import util::ppaux::ty_to_str;
+import driver::session::session;
 
 export create_local_var;
 export create_function;
@@ -249,8 +250,8 @@ fn create_block(cx: @block_ctxt) -> @metadata<block_md> {
     }*/
 
     let parent = alt cx.parent {
-      parent_none { create_function(cx.fcx).node }
-      parent_some(bcx) { create_block(bcx).node }
+        parent_none { create_function(cx.fcx).node }
+        parent_some(bcx) { create_block(bcx).node }
     };
     let file_node = create_file(bcx_ccx(cx), fname);
     let unique_id = alt cache.find(LexicalBlockTag) {
@@ -306,6 +307,8 @@ fn create_basic_type(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
         ast::ty_f32 {("f32", size_and_align_of::<f32>(), DW_ATE_float)}
         ast::ty_f64 {("f64", size_and_align_of::<f64>(), DW_ATE_float)}
       }}
+      _ { cx.tcx.sess.span_bug(ty.span,
+             "create_basic_type: unhandled type"); }
     };
 
     let fname = filename_from_span(cx, ty.span);
@@ -481,15 +484,15 @@ fn create_composite_type(type_tag: int, name: str, file: ValueRef, line: int,
     ret llmdnode(lldata);
 }
 
-fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t, vec_ty: @ast::ty)
+fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t,
+              vec_ty_span: codemap::span, elem_ty: @ast::ty)
     -> @metadata<tydesc_md> {
-    let fname = filename_from_span(cx, vec_ty.span);
+    let fname = filename_from_span(cx, vec_ty_span);
     let file_node = create_file(cx, fname);
-    let elem_ty = alt vec_ty.node { ast::ty_vec(mt) { mt.ty } };
     let elem_ty_md = create_ty(cx, elem_t, elem_ty);
     let tcx = ccx_tcx(cx);
     let scx = create_structure(file_node, ty_to_str(tcx, vec_t), 0);
-    let uint_ty = @{node: ast::ty_uint(ast::ty_u), span: vec_ty.span};
+    let uint_ty = @{node: ast::ty_uint(ast::ty_u), span: vec_ty_span};
     let size_t_type = create_basic_type(cx, ty::mk_uint(tcx), uint_ty);
     add_member(scx, "fill", 0, sys::size_of::<ctypes::size_t>() as int,
                sys::align_of::<ctypes::size_t>() as int, size_t_type.node);
@@ -516,12 +519,14 @@ fn member_size_and_align(ty: @ast::ty) -> (int, int) {
         ast::ty_i8 { size_and_align_of::<i8>() }
         ast::ty_i16 { size_and_align_of::<i16>() }
         ast::ty_i32 { size_and_align_of::<i32>() }
+        ast::ty_i64 { size_and_align_of::<i64>() }
       }}
       ast::ty_uint(m) { alt m {
         ast::ty_u { size_and_align_of::<uint>() }
         ast::ty_u8 { size_and_align_of::<i8>() }
         ast::ty_u16 { size_and_align_of::<u16>() }
         ast::ty_u32 { size_and_align_of::<u32>() }
+        ast::ty_u64 { size_and_align_of::<u64>() }
       }}
       ast::ty_float(m) { alt m {
         ast::ty_f { size_and_align_of::<float>() }
@@ -542,6 +547,7 @@ fn member_size_and_align(ty: @ast::ty) -> (int, int) {
       ast::ty_vec(_) {
         size_and_align_of::<ctypes::uintptr_t>()
       }
+      _ { fail "member_size_and_align: can't handle this type"; }
     }
 }
 
@@ -578,6 +584,9 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
           }
           ty::ty_vec(mt) { ast::ty_vec({ty: t_to_ty(cx, mt.ty, span),
                                         mut: mt.mut}) }
+          _ {
+            cx.tcx.sess.span_bug(span, "t_to_ty: Can't handle this type");
+          }
         };
         ret @{node: ty, span: span};
     }
@@ -586,6 +595,7 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
       ast::ty_box(mt) {
         let inner_t = alt ty::struct(ccx_tcx(cx), t) {
           ty::ty_box(boxed) { boxed.ty }
+          _ { cx.tcx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
         };
         let md = create_ty(cx, inner_t, mt.ty);
         let box = create_boxed_type(cx, t, inner_t, ty.span, md);
@@ -595,6 +605,8 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
       ast::ty_uniq(mt) {
         let inner_t = alt ty::struct(ccx_tcx(cx), t) {
           ty::ty_uniq(boxed) { boxed.ty }
+          // Hoping we'll have a way to eliminate this check soon.
+          _ { cx.tcx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
         };
         let md = create_ty(cx, inner_t, mt.ty);
         ret create_pointer_type(cx, t, ty.span, md);
@@ -611,7 +623,8 @@ fn create_ty(cx: @crate_ctxt, t: ty::t, ty: @ast::ty)
 
       ast::ty_vec(mt) {
         let inner_t = ty::sequence_element_type(ccx_tcx(cx), t);
-        let v = create_vec(cx, t, inner_t, ty);
+        let inner_ast_t = t_to_ty(cx, inner_t, mt.ty.span);
+        let v = create_vec(cx, t, inner_t, ty.span, inner_ast_t);
         ret create_pointer_type(cx, t, ty.span, v);
       }
 
@@ -650,15 +663,17 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
     let name = path_to_ident(alt pat_util::normalize_pat(bcx_tcx(bcx),
                                            local.node.pat).node {
       ast::pat_ident(ident, _) { ident /*XXX deal w/ optional node binding*/ }
-    });
+      _ { bcx_tcx(bcx).sess.span_bug(local.span, "create_local_var: \
+             weird pattern in local"); }
+     });
     let loc = codemap::lookup_char_pos(cx.sess.codemap,
                                        local.span.lo);
     let ty = base::node_id_type(cx, local.node.id);
     let tymd = create_ty(cx, ty, local.node.ty);
     let filemd = create_file(cx, loc.filename);
     let context = alt bcx.parent {
-      parent_none { create_function(bcx.fcx).node }
-      parent_some(_) { create_block(bcx).node }
+        parent_none { create_function(bcx.fcx).node }
+        parent_some(_) { create_block(bcx).node }
     };
     let mdnode = create_var(tg, context, name, filemd.node,
                             loc.line as int, tymd.node);
@@ -667,9 +682,15 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
 
     let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
       option::some(local_mem(v)) { v }
+      option::some(_) {
+        bcx_tcx(bcx).sess.span_bug(local.span, "local is bound to \
+                something weird");
+      }
       option::none {
         alt bcx.fcx.lllocals.get(local.node.pat.id) {
           local_imm(v) { v }
+          _ { bcx_tcx(bcx).sess.span_bug(local.span, "local is bound to \
+                something weird"); }
         }
       }
     };
@@ -745,15 +766,21 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
           ast::item_fn(decl, _, _) | ast::item_res(decl, _, _, _, _) {
             (item.ident, decl.output, item.id)
           }
+          _ { fcx_tcx(fcx).sess.span_bug(item.span, "create_function: item \
+                bound to non-function"); }
         }
       }
       ast_map::node_method(method) {
           (method.ident, method.decl.output, method.id)
       }
       ast_map::node_res_ctor(item) {
-        alt item.node { ast::item_res(decl, _, _, _, ctor_id) {
-          (item.ident, decl.output, ctor_id)
-        }}
+        alt item.node {
+            ast::item_res(decl, _, _, _, ctor_id) {
+              (item.ident, decl.output, ctor_id)
+            }
+            _ { fcx_tcx(fcx).sess.span_bug(item.span, "create_function: \
+                  expected an item_res here"); }
+          }
       }
       ast_map::node_expr(expr) {
         alt expr.node {
@@ -763,8 +790,12 @@ fn create_function(fcx: @fn_ctxt) -> @metadata<subprogram_md> {
           ast::expr_fn_block(decl, _) {
             (dbg_cx.names("fn"), decl.output, expr.id)
           }
+          _ { fcx_tcx(fcx).sess.span_bug(expr.span, "create_function: \
+                  expected an expr_fn or fn_block here"); }
         }
       }
+      _ { fcx_tcx(fcx).sess.bug("create_function: unexpected \
+            sort of node"); }
     };
 
     log(debug, ident);
diff --git a/src/comp/middle/gc.rs b/src/comp/middle/gc.rs
index 4bcc2a29d38..31b03cc3705 100644
--- a/src/comp/middle/gc.rs
+++ b/src/comp/middle/gc.rs
@@ -104,7 +104,7 @@ fn type_is_gc_relevant(cx: ty::ctxt, ty: ty::t) -> bool {
     alt ty::struct(cx, ty) {
       ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) |
       ty::ty_float(_) | ty::ty_uint(_) | ty::ty_str |
-      ty::ty_type | ty::ty_ptr(_) | ty::ty_native(_) {
+      ty::ty_type | ty::ty_send_type | ty::ty_ptr(_) | ty::ty_native(_) {
         ret false;
       }
       ty::ty_rec(fields) {
@@ -131,9 +131,19 @@ fn type_is_gc_relevant(cx: ty::ctxt, ty: ty::t) -> bool {
       ty::ty_constr(sub, _) { ret type_is_gc_relevant(cx, sub); }
       ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_fn(_) |
       ty::ty_param(_, _) | ty::ty_res(_, _, _) { ret true; }
+      ty::ty_opaque_closure_ptr(_) {
+        ret false; // I guess?
+      }
+      // A precondition to rule out these cases would be nice
       ty::ty_var(_) {
         fail "ty_var in type_is_gc_relevant";
       }
+      ty::ty_iface(_, _) {
+        fail "ty_iface in type_is_gc_relevant";
+      }
+      ty::ty_named(_,_) {
+        fail "ty_named in type_is_gc_relevant";
+      }
     }
 }
 
diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs
index c41b093225c..e06ce29add8 100644
--- a/src/comp/middle/kind.rs
+++ b/src/comp/middle/kind.rs
@@ -142,7 +142,9 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
           some(ex) {
             // All noncopyable fields must be overridden
             let t = ty::expr_ty(cx.tcx, ex);
-            let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } };
+            let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f }
+              _ { cx.tcx.sess.span_bug(ex.span,
+                     "Bad expr type in record"); } };
             for tf in ty_fields {
                 if !vec::any(fields, {|f| f.node.ident == tf.ident}) &&
                     !ty::kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) {
diff --git a/src/comp/middle/last_use.rs b/src/comp/middle/last_use.rs
index 190e88deae6..24b378b8d38 100644
--- a/src/comp/middle/last_use.rs
+++ b/src/comp/middle/last_use.rs
@@ -2,6 +2,7 @@ import syntax::{visit, ast_util};
 import syntax::ast::*;
 import syntax::codemap::span;
 import std::list::{is_not_empty, list, nil, cons, tail};
+import std::util::unreachable;
 import core::{vec, option};
 import std::list;
 
@@ -223,6 +224,11 @@ fn add_block_exit(cx: ctx, tp: block_type) -> bool {
             }
             cur = *tail;
           }
+          nil {
+            // typestate can't use the while loop condition --
+            // *sigh*
+            unreachable();
+          }
         }
     }
     ret false;
diff --git a/src/comp/middle/lint.rs b/src/comp/middle/lint.rs
index 838764171f0..f2f5666a346 100644
--- a/src/comp/middle/lint.rs
+++ b/src/comp/middle/lint.rs
@@ -51,6 +51,7 @@ fn merge_opts(attrs: [ast::attribute], cmd_opts: [(option, bool)]) ->
           ast::meta_word(name) {
             str_to_option(name)
           }
+          _ { fail "meta_to_option: meta_list contains a non-meta-word"; }
         };
     }
 
diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs
index ef40d4a87b2..736a31851d2 100644
--- a/src/comp/middle/mut.rs
+++ b/src/comp/middle/mut.rs
@@ -78,6 +78,10 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
               ty::ty_str {
                 ds += [@{mut: false, kind: index, outer_t: auto_unbox.t}];
               }
+              _ {
+                  tcx.sess.span_bug(base.span, "Ill-typed base expression in \
+                    index");
+              }
             }
             ds += auto_unbox.ds;
             ex = base;
@@ -92,6 +96,8 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
                   ty::ty_res(_, _, _) { }
                   ty::ty_enum(_, _) { }
                   ty::ty_ptr(mt) { is_mut = mt.mut == mut; ptr = true; }
+                  _ { tcx.sess.span_bug(base.span, "Ill-typed base \
+                        expression in deref"); }
                 }
                 ds += [@{mut: is_mut, kind: unbox(ptr && is_mut),
                          outer_t: base_t}];
diff --git a/src/comp/middle/pat_util.rs b/src/comp/middle/pat_util.rs
index 023d49db8a1..8a5c2706bb1 100644
--- a/src/comp/middle/pat_util.rs
+++ b/src/comp/middle/pat_util.rs
@@ -3,6 +3,7 @@ import syntax::ast_util;
 import syntax::ast_util::respan;
 import syntax::fold;
 import syntax::fold::*;
+import syntax::codemap::span;
 
 export normalize_arms;
 export normalize_pat;
@@ -80,10 +81,8 @@ type pat_id_map = std::map::hashmap<str, node_id>;
 // use the node_id of their namesake in the first pattern.
 fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
     let map = std::map::new_str_hash::<node_id>();
-    pat_bindings(normalize_pat(tcx, pat)) {|bound|
-        let name = path_to_ident(alt bound.node
-           { pat_ident(n, _) { n } });
-        map.insert(name, bound.id);
+    pat_bindings(normalize_pat(tcx, pat)) {|p_id, _s, n|
+      map.insert(path_to_ident(n), p_id);
     };
     ret map;
 }
@@ -91,10 +90,11 @@ fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
 // This does *not* normalize. The pattern should be already normalized
 // if you want to get a normalized pattern out of it.
 // Could return a constrained type in order to express that (future work)
-fn pat_bindings(pat: @pat, it: fn(@pat)) {
+fn pat_bindings(pat: @pat, it: fn(node_id, span, @path)) {
   alt pat.node {
-      pat_ident(_, option::none) { it(pat); }
-      pat_ident(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
+      pat_ident(pth, option::none) { it(pat.id, pat.span, pth); }
+      pat_ident(pth, option::some(sub)) { it(pat.id, pat.span, pth);
+        pat_bindings(sub, it); }
       pat_enum(_, sub) { for p in sub { pat_bindings(p, it); } }
       pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
       pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
@@ -106,7 +106,7 @@ fn pat_bindings(pat: @pat, it: fn(@pat)) {
 
 fn pat_binding_ids(pat: @pat) -> [node_id] {
     let found = [];
-    pat_bindings(pat) {|b| found += [b.id]; };
+    pat_bindings(pat) {|b_id, _sp, _pt| found += [b_id]; };
     ret found;
 }
 
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 2d3b9adc9bb..1c04541e764 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -45,15 +45,15 @@ enum scope {
 type scopes = list<scope>;
 
 enum import_state {
-    todo(ast::node_id, ast::ident, @[ast::ident], codemap::span, scopes),
-    is_glob(@[ast::ident], scopes, codemap::span),
+    todo(ast::node_id, ast::ident, @[ast::ident], span, scopes),
+    is_glob(@[ast::ident], scopes, span),
     resolving(span),
     resolved(option::t<def>, /* value */
              option::t<def>, /* type */
              option::t<def>, /* module */
              @[@_impl], /* impls */
              /* used for reporting unused import warning */
-             ast::ident, codemap::span),
+             ast::ident, span),
 }
 
 enum glob_import_state {
@@ -83,11 +83,13 @@ fn new_ext_hash() -> ext_hash {
 }
 
 enum mod_index_entry {
-    mie_view_item(@ast::view_item),
-    mie_import_ident(node_id, codemap::span),
+    mie_view_item(ident, node_id, span),
+    mie_import_ident(node_id, span),
     mie_item(@ast::item),
     mie_native_item(@ast::native_item),
-    mie_enum_variant(/* enum item */@ast::item, /* variant index */uint),
+    mie_enum_variant(/* variant index */uint,
+                     /*parts of enum item*/ [variant],
+                    node_id, span),
 }
 
 type mod_index = hashmap<ident, list<mod_index_entry>>;
@@ -278,6 +280,8 @@ fn map_crate(e: @env, c: @ast::crate) {
                   scope_crate {
                     e.mod_map.get(ast::crate_node_id).glob_imports += [glob];
                   }
+                  _ { e.sess.span_bug(vi.span, "Unexpected scope in a glob \
+                       import"); }
                 }
             }
           }
@@ -294,6 +298,7 @@ fn resolve_imports(e: env) {
             resolve_import(e, local_def(node_id), name, *path, span, scopes);
           }
           resolved(_, _, _, _, _, _) | is_glob(_, _, _) { }
+          _ { e.sess.bug("Shouldn't see a resolving in resolve_imports"); }
         }
     };
     e.used_imports.track = false;
@@ -478,7 +483,7 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
         if is_main_name([nm]) && !e.sess.building_library {
             // This is a main function -- set it in the session
             // as the main ID
-            e.sess.main_fn = some(id);
+            e.sess.main_fn = some((id, sp));
         }
       }
       _ { /* fallthrough */ }
@@ -665,6 +670,9 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
             lst(id,
                 option::get(e.mod_map.get(ast::crate_node_id).m).view_items)
           }
+          _ {
+              e.sess.bug("find_imports_after: nil or unexpected scope");
+          }
         }
     }
     // This function has cleanup code at the end. Do not return without going
@@ -904,6 +912,10 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
               ast::native_item_fn(decl, ty_params) {
                 ret lookup_in_fn(e, name, decl, ty_params, ns);
               }
+              _ {
+                  e.sess.span_bug(it.span, "lookup_in_scope: \
+                    scope_native_item doesn't refer to a native item");
+              }
             }
           }
           scope_bare_fn(decl, _, ty_params) |
@@ -1005,10 +1017,10 @@ fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
 fn lookup_in_pat(e: env, name: ident, pat: @ast::pat) -> option::t<def_id> {
     let found = none;
 
-    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat)) {|bound|
-        let p_name = alt bound.node { ast::pat_ident(n, _) { n } };
-        if str::eq(path_to_ident(p_name), name)
-                    { found = some(local_def(bound.id)); }
+    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat))
+     {|p_id, _sp, n|
+        if str::eq(path_to_ident(n), name)
+                    { found = some(local_def(p_id)); }
     };
     ret found;
 }
@@ -1114,6 +1126,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
               _ {}
             }
           }
+          _ { e.sess.span_bug(vi.span, "Unexpected view_item in block"); }
         }
     }
     ret none;
@@ -1189,16 +1202,16 @@ fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace,
       ast::def_native_mod(defid) {
         ret lookup_in_local_native_mod(e, defid.node, sp, name, ns);
       }
+      _ {
+          // Precondition
+          e.sess.span_bug(sp, "lookup_in_mod was passed a non-mod def");
+      }
     }
 }
 
-fn found_view_item(e: env, vi: @ast::view_item) -> option::t<def> {
-    alt vi.node {
-      ast::view_item_use(_, _, id) {
-        let cnum = cstore::get_use_stmt_cnum(e.cstore, id);
-        ret some(ast::def_mod({crate: cnum, node: ast::crate_node_id}));
-      }
-    }
+fn found_view_item(e: env, id: node_id) -> def {
+    let cnum = cstore::get_use_stmt_cnum(e.cstore, id);
+    ret ast::def_mod({crate: cnum, node: ast::crate_node_id});
 }
 
 fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
@@ -1220,6 +1233,9 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
         ret alt ns { ns_val(_) { val } ns_type { typ }
                      ns_module { md } };
       }
+      is_glob(_,_,_) {
+          e.sess.bug("lookup_import: can't handle is_glob");
+      }
     }
 }
 
@@ -1267,6 +1283,9 @@ fn lookup_in_globs(e: env, globs: [glob_imp_def], sp: span, id: ident,
           ast::view_item_import_glob(_, id) {
             if vec::member(id, e.ignored_imports) { ret none; }
           }
+          _ {
+            e.sess.span_bug(sp, "lookup_in_globs: not a glob");
+          }
         }
         alt lookup_in_mod(e, def.def, sp, name, ns, dr) {
           some(d) { option::some({def: d, item: def.item}) }
@@ -1322,24 +1341,20 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
 fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
    option::t<def> {
     alt mie {
-      mie_view_item(view_item) {
-        if ns == ns_module { ret found_view_item(e, view_item); }
+      mie_view_item(_, id, _) {
+         if ns == ns_module { ret some(found_view_item(e, id)); }
       }
       mie_import_ident(id, _) { ret lookup_import(e, local_def(id), ns); }
       mie_item(item) { ret found_def_item(item, ns); }
-      mie_enum_variant(item, variant_idx) {
-        alt item.node {
-          ast::item_enum(variants, _) {
-              alt ns {
-                  ns_val(_) {
-                     let vid = variants[variant_idx].node.id;
-                     ret some(ast::def_variant(local_def(item.id),
+      mie_enum_variant(variant_idx, variants, parent_id, parent_span) {
+         alt ns {
+            ns_val(_) {
+               let vid = variants[variant_idx].node.id;
+               ret some(ast::def_variant(local_def(parent_id),
                                         local_def(vid)));
-                  }
-                  _ { ret none::<def>; }
-              }
-          }
-        }
+            }
+            _ { ret none::<def>; }
+         }
       }
       mie_native_item(native_item) {
         alt native_item.node {
@@ -1374,8 +1389,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
     let index = new_str_hash::<list<mod_index_entry>>();
     for it: @ast::view_item in md.view_items {
         alt it.node {
-          ast::view_item_use(ident, _, _) {
-            add_to_index(index, ident, mie_view_item(it));
+          ast::view_item_use(ident, _, id) {
+           add_to_index(index, ident, mie_view_item(ident, id, it.span));
           }
           ast::view_item_import(ident, _, id) {
             add_to_index(index, ident, mie_import_ident(id, it.span));
@@ -1405,7 +1420,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
             let variant_idx: uint = 0u;
             for v: ast::variant in variants {
                 add_to_index(index, v.node.name,
-                             mie_enum_variant(it, variant_idx));
+                             mie_enum_variant(variant_idx, variants,
+                                             it.id, it.span));
                 variant_idx += 1u;
             }
           }
@@ -1418,8 +1434,9 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
     let index = new_str_hash::<list<mod_index_entry>>();
     for it: @ast::view_item in md.view_items {
         alt it.node {
-          ast::view_item_use(ident, _, _) {
-            add_to_index(index, ident, mie_view_item(it));
+          ast::view_item_use(ident, _, id) {
+            add_to_index(index, ident, mie_view_item(ident, id,
+                                                     it.span));
           }
           ast::view_item_import(ident, _, id) {
             add_to_index(index, ident, mie_import_ident(id, it.span));
@@ -1431,6 +1448,7 @@ fn index_nmod(md: ast::native_mod) -> mod_index {
             }
           }
           ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) { }
+          _ { /* tag exports */ }
         }
     }
     for it: @ast::native_item in md.items {
@@ -1450,6 +1468,7 @@ fn ns_for_def(d: def) -> namespace {
       ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
       ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
       ast::def_native_ty(_) { ns_type }
+      ast::def_ty_param(_, _) { ns_type }
     }
 }
 
@@ -1529,10 +1548,10 @@ fn check_mod_name(e: env, name: ident, entries: list<mod_index_entry>) {
 
 fn mie_span(mie: mod_index_entry) -> span {
     ret alt mie {
-          mie_view_item(item) { item.span }
+          mie_view_item(_, _, span) { span }
           mie_import_ident(_, span) { span }
           mie_item(item) { item.span }
-          mie_enum_variant(item, _) { item.span }
+          mie_enum_variant(_, _, _, span) { span }
           mie_native_item(item) { item.span }
         };
 }
@@ -1559,9 +1578,8 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
 }
 
 fn check_pat(e: @env, ch: checker, p: @ast::pat) {
-    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|p|
-        let ident = path_to_ident(alt p.node { pat_ident(n, _) { n } });
-        add_name(ch, p.span, ident);
+    pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|_i, p_sp, n|
+       add_name(ch, p_sp, path_to_ident(n));
     };
 }
 
@@ -1607,14 +1625,13 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
               ast::decl_local(locs) {
                 let local_values = checker(*e, "value");
                 for (_, loc) in locs {
-                        pat_util::pat_bindings
-                            (normalize_pat_def_map(e.def_map, loc.node.pat))
-                            {|p|
-                            let ident = path_to_ident(alt p.node
-                                 { pat_ident(n, _) { n } });
-                        add_name(local_values, p.span, ident);
-                        check_name(values, p.span, ident);
-                    };
+                     pat_util::pat_bindings
+                        (normalize_pat_def_map(e.def_map, loc.node.pat))
+                            {|_i, p_sp, n|
+                            let ident = path_to_ident(n);
+                            add_name(local_values, p_sp, ident);
+                            check_name(values, p_sp, ident);
+                          };
                 }
               }
               ast::decl_item(it) {
@@ -1807,8 +1824,9 @@ fn check_exports(e: @env) {
                             some(ms) {
                                 list::iter(ms) {|m|
                                    alt m {
-                                     mie_enum_variant(parent_item,_) {
-                                       if parent_item.id != parent_id {
+                                     mie_enum_variant(_, _, actual_parent_id,
+                                                     _) {
+                                       if actual_parent_id != parent_id {
                                           e.sess.span_err(vi.span,
                                            #fmt("variant %s \
                                            doesn't belong to enum %s",
@@ -1860,6 +1878,10 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
                            scopes);
             alt e.imports.get(id) {
               resolved(_, _, _, is, _, _) { act(is); }
+              _ {
+                  e.sess.bug("Undocumented invariant in \
+                    lookup_imported_impls");
+              }
             }
           }
           _ {}
@@ -1899,6 +1921,8 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
                 _ {}
               }
             }
+            _ { e.sess.span_bug(vi.span, "Undocumented invariant in \
+                  find_impls_in_view_item"); }
           }
       }
       _ {}
diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs
index 7612148df45..69c08d68e20 100644
--- a/src/comp/middle/shape.rs
+++ b/src/comp/middle/shape.rs
@@ -451,6 +451,12 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
       ty::ty_opaque_closure_ptr(_) {
         s += [shape_opaque_closure_ptr];
       }
+      ty::ty_constr(inner_t, _) {
+        s += shape_of(ccx, inner_t, ty_param_map);
+      }
+      ty::ty_named(_, _) {
+        ccx.tcx.sess.bug("shape_of: shouldn't see a ty_named");
+      }
     }
 
     ret s;
@@ -699,6 +705,7 @@ fn static_size_of_enum(cx: @crate_ctxt, t: ty::t)
         cx.enum_sizes.insert(t, max_size);
         ret max_size;
       }
+      _ { cx.tcx.sess.bug("static_size_of_enum called on non-enum"); }
     }
 }
 
@@ -779,6 +786,11 @@ fn dynamic_metrics(cx: @block_ctxt, t: ty::t) -> metrics {
 
         { bcx: bcx, sz: sz, align: C_int(ccx, 1) }
       }
+      _ {
+        // Precondition?
+        bcx_tcx(cx).sess.bug("dynamic_metrics: type has static \
+          size");
+      }
     }
 }
 
diff --git a/src/comp/middle/trans/alt.rs b/src/comp/middle/trans/alt.rs
index 9cd237828ff..a18a6bb1aa1 100644
--- a/src/comp/middle/trans/alt.rs
+++ b/src/comp/middle/trans/alt.rs
@@ -21,7 +21,7 @@ import common::*;
 // range)
 enum opt {
     lit(@ast::expr),
-    var(/* disr val */int, /* variant dids */{tg: def_id, var: def_id}),
+    var(/* disr val */int, /* variant dids */{enm: def_id, var: def_id}),
     range(@ast::expr, @ast::expr)
 }
 fn opt_eq(a: opt, b: opt) -> bool {
@@ -69,7 +69,7 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result {
 // FIXME: invariant -- pat_id is bound in the def_map?
 fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt {
     let vdef = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat_id));
-    let variants = ty::enum_variants(ccx.tcx, vdef.tg);
+    let variants = ty::enum_variants(ccx.tcx, vdef.enm);
     for v: ty::variant_info in *variants {
         if vdef.var == v.id { ret var(v.disr_val, vdef); }
     }
@@ -262,24 +262,24 @@ fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] {
 }
 
 fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
-                        vdefs: {tg: def_id, var: def_id}, val: ValueRef) ->
+                        vdefs: {enm: def_id, var: def_id}, val: ValueRef) ->
    {vals: [ValueRef], bcx: @block_ctxt} {
     let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
     // invariant:
     // pat_id must have the same length ty_param_substs as vdefs?
     let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
     let blobptr = val;
-    let variants = ty::enum_variants(ccx.tcx, vdefs.tg);
+    let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
     let args = [];
     let size =
-        vec::len(ty::enum_variant_with_id(ccx.tcx, vdefs.tg, vdefs.var).args);
+       vec::len(ty::enum_variant_with_id(ccx.tcx, vdefs.enm, vdefs.var).args);
     if size > 0u && vec::len(*variants) != 1u {
         let enumptr =
             PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
         blobptr = GEPi(bcx, enumptr, [0, 1]);
     }
     let i = 0u;
-    let vdefs_tg = vdefs.tg;
+    let vdefs_tg = vdefs.enm;
     let vdefs_var = vdefs.var;
     while i < size {
         check (valid_variant_index(i, bcx, vdefs_tg, vdefs_var));
@@ -423,8 +423,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     // Separate path for extracting and binding record fields
     if vec::len(rec_fields) > 0u {
         let rec_ty = ty::node_id_to_type(ccx.tcx, pat_id);
-        let fields =
-            alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
+        let fields = ty::get_fields(ccx.tcx, rec_ty);
         let rec_vals = [];
         for field_name: ast::ident in rec_fields {
             let ix = option::get(ty::field_idx(field_name, fields));
@@ -444,6 +443,10 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
         let n_tup_elts =
             alt ty::struct(ccx.tcx, tup_ty) {
               ty::ty_tup(elts) { vec::len(elts) }
+              _ {
+                  ccx.sess.bug("Non-tuple type in tuple\
+                    pattern");
+              }
             };
         let tup_vals = [], i = 0u;
         while i < n_tup_elts {
@@ -483,7 +486,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
     if vec::len(opts) > 0u {
         alt opts[0] {
           var(_, vdef) {
-            if vec::len(*ty::enum_variants(ccx.tcx, vdef.tg)) == 1u {
+            if vec::len(*ty::enum_variants(ccx.tcx, vdef.enm)) == 1u {
                 kind = single;
             } else {
                 let enumptr =
@@ -541,6 +544,8 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
                 llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
                 bcx = r.bcx;
               }
+              _ { bcx_tcx(bcx).sess.bug("Someone forgot to\
+                    document an invariant in compile_submatch"); }
             }
           }
           compare {
@@ -624,8 +629,11 @@ fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
         // Copy references that the alias analysis considered unsafe
         ids.values {|node_id|
             if bcx_ccx(bcx).copy_map.contains_key(node_id) {
-                let local = alt bcx.fcx.lllocals.get(node_id) {
-                  local_mem(x) { x }
+                let local = alt bcx.fcx.lllocals.find(node_id) {
+                  some(local_mem(x)) { x }
+                  _ { bcx_tcx(bcx).sess.bug("Someone \
+                        forgot to document an invariant in \
+                        make_phi_bindings"); }
                 };
                 let e_ty = ty::node_id_to_type(bcx_tcx(bcx), node_id);
                 let {bcx: abcx, val: alloc} = base::alloc_ty(bcx, e_ty);
@@ -745,8 +753,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
       }
       ast::pat_rec(fields, _) {
         let rec_ty = ty::node_id_to_type(ccx.tcx, pat.id);
-        let rec_fields =
-            alt ty::struct(ccx.tcx, rec_ty) { ty::ty_rec(fields) { fields } };
+        let rec_fields = ty::get_fields(ccx.tcx, rec_ty);
         for f: ast::field_pat in fields {
             let ix = option::get(ty::field_idx(f.ident, rec_fields));
             // how to get rid of this check?
diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs
index 85c23f4937c..7bff9b25060 100644
--- a/src/comp/middle/trans/base.rs
+++ b/src/comp/middle/trans/base.rs
@@ -42,6 +42,7 @@ import link::{mangle_internal_name_by_type_only,
 import metadata::{csearch, cstore};
 import util::ppaux::{ty_to_str, ty_to_short_str};
 
+import shape::static_size_of_enum;
 import common::*;
 import build::*;
 
@@ -489,37 +490,6 @@ fn simplify_type(ccx: @crate_ctxt, typ: ty::t) -> ty::t {
     ret ty::fold_ty(ccx.tcx, ty::fm_general(bind simplifier(ccx, _)), typ);
 }
 
-
-// Computes the size of the data part of a non-dynamically-sized enum.
-fn static_size_of_enum(cx: @crate_ctxt, t: ty::t)
-    : type_has_static_size(cx, t) -> uint {
-    if cx.enum_sizes.contains_key(t) { ret cx.enum_sizes.get(t); }
-    alt ty::struct(cx.tcx, t) {
-      ty::ty_enum(tid, subtys) {
-        // Compute max(variant sizes).
-
-        let max_size = 0u;
-        let variants = ty::enum_variants(cx.tcx, tid);
-        for variant: ty::variant_info in *variants {
-            let tup_ty = simplify_type(cx, ty::mk_tup(cx.tcx, variant.args));
-            // Perform any type parameter substitutions.
-
-            tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
-            // Here we possibly do a recursive call.
-
-            // FIXME: Avoid this check. Since the parent has static
-            // size, any field must as well. There should be a way to
-            // express that with constrained types.
-            check (type_has_static_size(cx, tup_ty));
-            let this_size = llsize_of_real(cx, type_of(cx, tup_ty));
-            if max_size < this_size { max_size = this_size; }
-        }
-        cx.enum_sizes.insert(t, max_size);
-        ret max_size;
-      }
-    }
-}
-
 fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
     fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
         //
@@ -600,6 +570,9 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
             } else { max_size_val };
         ret rslt(bcx, total_size);
       }
+      // Precondition?
+      _ { bcx_tcx(cx).sess.fatal("trans::dynamic_size_of alled on something \
+            with static size"); }
     }
 }
 
@@ -634,6 +607,8 @@ fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result {
         }
         ret rslt(bcx, a);
       }
+      _ { bcx_tcx(cx).sess.bug("trans::dynamic_align_of called on \
+            something with static size"); }
     }
 }
 
@@ -1457,16 +1432,16 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
       ty::ty_int(_) { ret rslt(cx, f(signed_int)); }
       ty::ty_uint(_) { ret rslt(cx, f(unsigned_int)); }
       ty::ty_float(_) { ret rslt(cx, f(floating_point)); }
+      ty::ty_native(_) {
+        let cx = trans_fail(cx, none::<span>,
+                            "attempt to compare values of type native");
+        ret rslt(cx, C_nil());
+      }
       ty::ty_type {
         ret rslt(trans_fail(cx, none,
                             "attempt to compare values of type type"),
                  C_nil());
       }
-      ty::ty_native(_) {
-        let cx = trans_fail(cx, none,
-                            "attempt to compare values of type native");
-        ret rslt(cx, C_nil());
-      }
       _ {
         // Should never get here, because t is scalar.
         bcx_ccx(cx).sess.bug("non-scalar type passed to \
@@ -1479,6 +1454,11 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
 // A helper function to do the actual comparison of scalar values.
 fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
                          nt: scalar_type, op: ast::binop) -> ValueRef {
+    fn die_(cx: @block_ctxt) -> ! {
+        bcx_tcx(cx).sess.bug("compare_scalar_values: must be a\
+          comparison operator");
+    }
+    let die = bind die_(cx);
     alt nt {
       nil_type {
         // We don't need to do actual comparisons for nil.
@@ -1486,6 +1466,8 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
         alt op {
           ast::eq | ast::le | ast::ge { ret C_bool(true); }
           ast::ne | ast::lt | ast::gt { ret C_bool(false); }
+          // refinements would be nice
+          _ { die(); }
         }
       }
       floating_point {
@@ -1496,6 +1478,7 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
           ast::le { lib::llvm::LLVMRealOLE }
           ast::gt { lib::llvm::LLVMRealOGT }
           ast::ge { lib::llvm::LLVMRealOGE }
+          _ { die(); }
         };
         ret FCmp(cx, cmp, lhs, rhs);
       }
@@ -1507,6 +1490,7 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
           ast::le { lib::llvm::LLVMIntSLE }
           ast::gt { lib::llvm::LLVMIntSGT }
           ast::ge { lib::llvm::LLVMIntSGE }
+          _ { die(); }
         };
         ret ICmp(cx, cmp, lhs, rhs);
       }
@@ -1518,6 +1502,7 @@ fn compare_scalar_values(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
           ast::le { lib::llvm::LLVMIntULE }
           ast::gt { lib::llvm::LLVMIntUGT }
           ast::ge { lib::llvm::LLVMIntUGE }
+          _ { die(); }
         };
         ret ICmp(cx, cmp, lhs, rhs);
       }
@@ -1574,6 +1559,8 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t,
                 j += 1u;
             }
           }
+          // Precondition?
+          _ { bcx_tcx(cx).sess.bug("iter_variant: not a function type"); }
         }
         ret cx;
     }
@@ -1846,6 +1833,8 @@ fn drop_ty_immediate(bcx: @block_ctxt, v: ValueRef, t: ty::t) -> @block_ctxt {
     alt ty::struct(bcx_tcx(bcx), t) {
       ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { free_ty(bcx, v, t) }
       ty::ty_box(_) | ty::ty_iface(_, _) { decr_refcnt_maybe_free(bcx, v, t) }
+      // Precondition?
+      _ { bcx_tcx(bcx).sess.bug("drop_ty_immediate: non-box ty"); }
     }
 }
 
@@ -2112,6 +2101,9 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
       ast::eq | ast::ne { llop = C_u8(abi::cmp_glue_op_eq); }
       ast::lt | ast::ge { llop = C_u8(abi::cmp_glue_op_lt); }
       ast::le | ast::gt { llop = C_u8(abi::cmp_glue_op_le); }
+      // Precondition?
+      _ { bcx_tcx(cx).sess.bug("trans_compare got\
+              non-comparison-op"); }
     }
 
     let rs = call_cmp_glue(cx, lhs, rhs, rhs_t, llop);
@@ -2122,6 +2114,8 @@ fn trans_compare(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
       ast::ne | ast::ge | ast::gt {
         ret rslt(rs.bcx, Not(rs.bcx, rs.val));
       }
+      _ { bcx_tcx(cx).sess.bug("trans_compare got\
+              non-comparison-op"); }
     }
 }
 
@@ -2272,9 +2266,12 @@ fn autoderef(cx: @block_ctxt, v: ValueRef, t: ty::t) -> result_t {
     ret {bcx: cx, val: v1, ty: t1};
 }
 
-fn trans_lazy_binop(bcx: @block_ctxt, op: ast::binop, a: @ast::expr,
+// refinement types would obviate the need for this
+enum lazy_binop_ty { lazy_and, lazy_or }
+
+fn trans_lazy_binop(bcx: @block_ctxt, op: lazy_binop_ty, a: @ast::expr,
                     b: @ast::expr, dest: dest) -> @block_ctxt {
-    let is_and = alt op { ast::and { true } ast::or { false } };
+    let is_and = alt op { lazy_and { true } lazy_or { false } };
     let lhs_res = trans_temp_expr(bcx, a);
     if lhs_res.bcx.unreachable { ret lhs_res.bcx; }
     let rhs_cx = new_scope_block_ctxt(lhs_res.bcx, "rhs");
@@ -2321,8 +2318,11 @@ fn trans_binary(bcx: @block_ctxt, op: ast::binop, lhs: @ast::expr,
 
     // First couple cases are lazy:
     alt op {
-      ast::and | ast::or {
-        ret trans_lazy_binop(bcx, op, lhs, rhs, dest);
+      ast::and {
+        ret trans_lazy_binop(bcx, lazy_and, lhs, rhs, dest);
+      }
+      ast::or {
+        ret trans_lazy_binop(bcx, lazy_or, lhs, rhs, dest);
       }
       _ {
         // Remaining cases are eager:
@@ -2394,7 +2394,11 @@ fn store_in_dest(bcx: @block_ctxt, val: ValueRef, dest: dest) -> @block_ctxt {
 }
 
 fn get_dest_addr(dest: dest) -> ValueRef {
-    alt dest { save_in(a) { a } }
+    alt dest {
+       save_in(a) { a }
+       // Precondition?
+       _ { fail "get_dest_addr: not a save_in"; }
+    }
 }
 
 fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
@@ -2425,6 +2429,9 @@ fn trans_if(cx: @block_ctxt, cond: @ast::expr, thn: ast::blk,
           ast::expr_block(blk) {
             else_cx = trans_block_dps(else_cx, blk, else_dest);
           }
+          // would be nice to have a constraint on ifs
+          _ { bcx_tcx(cx).sess.bug("Strange alternative\
+                in if"); }
         }
       }
       _ {}
@@ -2691,7 +2698,12 @@ fn trans_rec_field(bcx: @block_ctxt, base: @ast::expr,
                    field: ast::ident) -> lval_result {
     let {bcx, val} = trans_temp_expr(bcx, base);
     let {bcx, val, ty} = autoderef(bcx, val, ty::expr_ty(bcx_tcx(bcx), base));
-    let fields = alt ty::struct(bcx_tcx(bcx), ty) { ty::ty_rec(fs) { fs } };
+    let fields = alt ty::struct(bcx_tcx(bcx), ty) {
+            ty::ty_rec(fs) { fs }
+            // Constraint?
+            _ { bcx_tcx(bcx).sess.span_bug(base.span, "trans_rec_field:\
+                 base expr has non-record type"); }
+        };
     let ix = option::get(ty::field_idx(field, fields));
     // Silly check
     check type_is_tup_like(bcx, ty);
@@ -2763,6 +2775,9 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
               some(origin) { // An impl method
                 ret impl::trans_method_callee(bcx, e.id, base, origin);
               }
+              // Precondition?
+              _ { bcx_tcx(bcx).sess.span_bug(e.span, "trans_callee: weird\
+                    expr"); }
             }
         }
       }
@@ -2809,6 +2824,11 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
                 PointerCast(sub.bcx, sub.val, ellty)
               }
               ty::ty_ptr(_) | ty::ty_uniq(_) { sub.val }
+              // Precondition?
+              _ {
+                  bcx_tcx(cx).sess.span_bug(e.span, "trans_lval:\
+                    Weird argument in deref");
+              }
             };
         ret lval_owned(sub.bcx, val);
       }
@@ -2949,6 +2969,7 @@ fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
               integral {int_cast(e_res.bcx, ll_t_out,
                                   val_ty(lldiscrim_a), lldiscrim_a, true)}
               float {SIToFP(e_res.bcx, lldiscrim_a, ll_t_out)}
+              _ { ccx.sess.bug("Translating unsupported cast.") }
             }
           }
           _ { ccx.sess.bug("Translating unsupported cast.") }
@@ -2990,7 +3011,7 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty: TypeRef,
         if arg.mode == ast::by_val && (lv.kind == owned || !imm) {
             val = Load(bcx, val);
         }
-    } else if arg.mode == ast::by_copy {
+        } else if arg.mode == ast::by_copy {
         let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
         let last_use = ccx.last_uses.contains_key(e.id);
         bcx = cx;
@@ -3341,6 +3362,7 @@ fn trans_tup(bcx: @block_ctxt, elts: [@ast::expr], id: ast::node_id,
         ret bcx;
       }
       save_in(pos) { pos }
+      _ { bcx_tcx(bcx).sess.bug("trans_tup: weird dest"); }
     };
     let temp_cleanups = [], i = 0;
     for e in elts {
@@ -3368,9 +3390,12 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field],
         ret bcx;
       }
       save_in(pos) { pos }
+      _ { bcx_tcx(bcx).sess.bug("trans_rec: weird dest"); }
     };
 
-    let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f } };
+    let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f }
+      _ { bcx_tcx(bcx).sess.bug("trans_rec: id doesn't\
+           have a record type") } };
     let temp_cleanups = [];
     for fld in fields {
         let ix = option::get(vec::position_pred(ty_fields, {|ft|
@@ -3644,6 +3669,9 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
         assert dest == ignore;
         ret trans_assign_op(bcx, e, op, dst, src);
       }
+      _ { bcx_tcx(bcx).sess.span_bug(e.span, "trans_expr reached\
+             fall-through case"); }
+
     }
 }
 
@@ -3914,9 +3942,18 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
     let ty = node_id_type(bcx_ccx(bcx), local.node.id);
     let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
       some(local_mem(v)) { v }
+      some(_) { bcx_tcx(bcx).sess.span_bug(local.span,
+                        "init_local: Someone forgot to document why it's\
+                         safe to assume local.node.init must be local_mem!");
+      }
       // This is a local that is kept immediate
       none {
-        let initexpr = alt local.node.init { some({expr, _}) { expr } };
+        let initexpr = alt local.node.init {
+                some({expr, _}) { expr }
+                none { bcx_tcx(bcx).sess.span_bug(local.span,
+                        "init_local: Someone forgot to document why it's\
+                         safe to assume local.node.init isn't none!"); }
+            };
         let {bcx, val, kind} = trans_temp_lval(bcx, initexpr);
         if kind != temporary {
             if kind == owned { val = Load(bcx, val); }
@@ -3952,6 +3989,8 @@ fn init_ref_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
     alt kind {
       owned_imm { val = do_spill_noroot(bcx, val); }
       owned {}
+      _ { bcx_tcx(bcx).sess.span_bug(local.span,
+           "Someone forgot to document an invariant in init_ref_local!"); }
     }
     ret alt::bind_irrefutable_pat(bcx, local.node.pat, val, false);
 }
@@ -4388,9 +4427,15 @@ fn create_llargs_for_fn_args(cx: @fn_ctxt, ty_self: self_arg,
 fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
                         arg_tys: [ty::arg]) -> @block_ctxt {
     let arg_n: uint = 0u, bcx = bcx;
+    fn epic_fail_(bcx: @block_ctxt) -> ! {
+        bcx_tcx(bcx).sess.bug("Someone forgot\
+                to document an invariant in copy_args_to_allocas!");
+    }
+    let epic_fail = bind epic_fail_(bcx);
     for arg in arg_tys {
         let id = args[arg_n].id;
-        let argval = alt fcx.llargs.get(id) { local_mem(v) { v } };
+        let argval = alt fcx.llargs.get(id) { local_mem(v) { v }
+                                              _ { epic_fail() } };
         alt arg.mode {
           ast::by_mut_ref { }
           ast::by_move | ast::by_copy { add_clean(bcx, argval, arg.ty); }
@@ -4405,6 +4450,7 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
             }
           }
           ast::by_ref {}
+          _ { epic_fail(); }
         }
         if fcx_ccx(fcx).sess.opts.extra_debuginfo {
             debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
@@ -4414,9 +4460,13 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
     ret bcx;
 }
 
+// cries out for a precondition
 fn arg_tys_of_fn(ccx: @crate_ctxt, id: ast::node_id) -> [ty::arg] {
-    alt ty::struct(ccx.tcx, ty::node_id_to_type(ccx.tcx, id)) {
+    let tt = ty::node_id_to_type(ccx.tcx, id);
+    alt ty::struct(ccx.tcx, tt) {
       ty::ty_fn({inputs, _}) { inputs }
+      _ { ccx.sess.bug(#fmt("arg_tys_of_fn called on non-function\
+            type %s", ty_to_str(ccx.tcx, tt)));}
     }
 }
 
@@ -4438,14 +4488,14 @@ enum self_arg { impl_self(ty::t), no_self, }
 // trans_closure: Builds an LLVM function out of a source function.
 // If the function closes over its environment a closure will be
 // returned.
-fn trans_closure(cx: @local_ctxt, sp: span, decl: ast::fn_decl,
+fn trans_closure(cx: @local_ctxt, decl: ast::fn_decl,
                  body: ast::blk, llfndecl: ValueRef,
                  ty_self: self_arg, ty_params: [ast::ty_param],
                  id: ast::node_id, maybe_load_env: fn(@fn_ctxt)) {
     set_uwtable(llfndecl);
 
     // Set up arguments to the function.
-    let fcx = new_fn_ctxt_w_id(cx, llfndecl, id, decl.cf, some(sp));
+    let fcx = new_fn_ctxt_w_id(cx, llfndecl, id, decl.cf, some(body.span));
     create_llargs_for_fn_args(fcx, ty_self, decl.inputs, ty_params);
 
     // Create the first basic block in the function and keep a handle on it to
@@ -4480,7 +4530,7 @@ fn trans_closure(cx: @local_ctxt, sp: span, decl: ast::fn_decl,
 
 // trans_fn: creates an LLVM function corresponding to a source language
 // function.
-fn trans_fn(cx: @local_ctxt, sp: span, decl: ast::fn_decl, body: ast::blk,
+fn trans_fn(cx: @local_ctxt, decl: ast::fn_decl, body: ast::blk,
             llfndecl: ValueRef, ty_self: self_arg, ty_params: [ast::ty_param],
             id: ast::node_id) {
     let do_time = cx.ccx.sess.opts.stats;
@@ -4490,7 +4540,7 @@ fn trans_fn(cx: @local_ctxt, sp: span, decl: ast::fn_decl, body: ast::blk,
                     {sec: 0u32, usec: 0u32}
                 };
     let fcx = option::none;
-    trans_closure(cx, sp, decl, body, llfndecl, ty_self, ty_params, id,
+    trans_closure(cx, decl, body, llfndecl, ty_self, ty_params, id,
                   {|new_fcx| fcx = option::some(new_fcx);});
     if cx.ccx.sess.opts.extra_debuginfo {
         debuginfo::create_function(option::get(fcx));
@@ -4516,6 +4566,8 @@ fn trans_res_ctor(cx: @local_ctxt, dtor: ast::fn_decl,
     let tup_t = ty::mk_tup(ccx.tcx, [ty::mk_int(ccx.tcx), arg_t]);
     let arg = alt fcx.llargs.find(dtor.inputs[0].id) {
       some(local_mem(x)) { x }
+      _ { ccx.sess.bug("Someone forgot to document an invariant \
+            in trans_res_ctor"); }
     };
     let llretptr = fcx.llretptr;
     if ty::type_has_dynamic_size(ccx.tcx, ret_t) {
@@ -4603,7 +4655,9 @@ fn trans_enum_variant(cx: @local_ctxt, enum_id: ast::node_id,
         // If this argument to this function is a enum, it'll have come in to
         // this function as an opaque blob due to the way that type_of()
         // works. So we have to cast to the destination's view of the type.
-        let llarg = alt fcx.llargs.find(va.id) { some(local_mem(x)) { x } };
+        let llarg = alt fcx.llargs.find(va.id) { some(local_mem(x)) { x }
+          _ { bcx_tcx(bcx).sess.span_fatal(variant.span, "Someone forgot\
+                to document an invariant in trans_tag_variant"); } };
         let arg_ty = arg_tys[i].ty;
         if ty::type_contains_params(bcx_tcx(bcx), arg_ty) {
             lldestptr = PointerCast(bcx, lldestptr, val_ty(llarg));
@@ -4733,6 +4787,10 @@ fn c_stack_tys(ccx: @crate_ctxt,
             shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void())
         };
       }
+      _ {
+          // Precondition?
+          ccx.tcx.sess.bug("c_stack_tys called on non-function type");
+      }
     }
 }
 
@@ -4889,7 +4947,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
         let sub_cx = extend_path(cx, item.ident);
         alt cx.ccx.item_ids.find(item.id) {
           some(llfndecl) {
-            trans_fn(sub_cx, item.span, decl, body, llfndecl, no_self, tps,
+            trans_fn(sub_cx, decl, body, llfndecl, no_self, tps,
                      item.id);
           }
           _ {
@@ -4907,7 +4965,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
         // Create a function for the destructor
         alt cx.ccx.item_ids.find(item.id) {
           some(lldtor_decl) {
-            trans_fn(cx, item.span, decl, body, lldtor_decl, no_self,
+            trans_fn(cx, decl, body, lldtor_decl, no_self,
                      tps, dtor_id);
           }
           _ {
@@ -4998,8 +5056,10 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
     }
 
     let main_takes_argv =
+        // invariant!
         alt ty::struct(ccx.tcx, main_node_type) {
           ty::ty_fn({inputs, _}) { vec::len(inputs) != 0u }
+          _ { ccx.sess.span_fatal(sp, "main has a non-function type"); }
         };
 
     let llfn = create_main(ccx, main_llfn, main_takes_argv);
@@ -5094,7 +5154,10 @@ fn fill_fn_pair(bcx: @block_ctxt, pair: ValueRef, llfn: ValueRef,
 fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
     let count;
     let native_item =
-        alt cx.ast_map.find(id) { some(ast_map::node_native_item(i)) { i } };
+        // invariant?!
+        alt cx.ast_map.find(id) { some(ast_map::node_native_item(i)) { i }
+         _ { cx.sess.bug("native_fn_ty_param_count\
+                         given a non-native item"); } };
     alt native_item.node {
       ast::native_item_ty {
         cx.sess.bug("register_native_fn(): native fn isn't \
@@ -5107,13 +5170,17 @@ fn native_fn_ty_param_count(cx: @crate_ctxt, id: ast::node_id) -> uint {
     ret count;
 }
 
-fn native_fn_wrapper_type(cx: @crate_ctxt,
+
+// TODO: precondition
+fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span,
                           param_bounds: [ty::param_bounds],
                           x: ty::t) -> TypeRef {
     alt ty::struct(cx.tcx, x) {
       ty::ty_fn({inputs: args, output: out, _}) {
         ret type_of_fn(cx, args, out, param_bounds);
       }
+      _ { cx.sess.span_bug(sp, "native_fn_wrapper_type got ill-typed\
+              thing"); }
     }
 }
 
diff --git a/src/comp/middle/trans/closure.rs b/src/comp/middle/trans/closure.rs
index ed1d5e9158a..4ff6d6fca2b 100644
--- a/src/comp/middle/trans/closure.rs
+++ b/src/comp/middle/trans/closure.rs
@@ -520,7 +520,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
         let cap_vars = capture::compute_capture_vars(
             ccx.tcx, id, proto, cap_clause);
         let {llbox, cbox_ty, bcx} = build_closure(bcx, cap_vars, ck);
-        trans_closure(sub_cx, sp, decl, body, llfn, no_self, [], id, {|fcx|
+        trans_closure(sub_cx, decl, body, llfn, no_self, [], id, {|fcx|
             load_environment(bcx, fcx, cbox_ty, cap_vars, ck);
         });
         llbox
@@ -532,7 +532,7 @@ fn trans_expr_fn(bcx: @block_ctxt,
       ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
       ast::proto_bare {
         let closure = C_null(T_opaque_cbox_ptr(ccx));
-        trans_closure(sub_cx, sp, decl, body, llfn, no_self, [],
+        trans_closure(sub_cx, decl, body, llfn, no_self, [],
                       id, {|_fcx|});
         closure
       }
diff --git a/src/comp/middle/trans/common.rs b/src/comp/middle/trans/common.rs
index 57c74d1bad3..96cc79a6db2 100644
--- a/src/comp/middle/trans/common.rs
+++ b/src/comp/middle/trans/common.rs
@@ -414,6 +414,9 @@ fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
     if cx.kind != NON_SCOPE_BLOCK { ret cx; }
     alt cx.parent {
       parent_some(b) { ret find_scope_cx(b); }
+      _ {
+          bcx_tcx(cx).sess.bug("find_scope_cx: empty scope");
+      }
     }
 }
 
diff --git a/src/comp/middle/trans/impl.rs b/src/comp/middle/trans/impl.rs
index 0798e0236f5..ded05d4bc0c 100644
--- a/src/comp/middle/trans/impl.rs
+++ b/src/comp/middle/trans/impl.rs
@@ -2,6 +2,7 @@ import core::ctypes::c_uint;
 import base::*;
 import common::*;
 import build::*;
+import driver::session::session;
 import option::{some, none};
 import syntax::{ast, ast_util};
 import metadata::csearch;
@@ -45,10 +46,13 @@ fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
     for m in methods {
         alt cx.ccx.item_ids.find(m.id) {
           some(llfn) {
-            trans_fn(extend_path(sub_cx, m.ident), m.span, m.decl, m.body,
+            trans_fn(extend_path(sub_cx, m.ident), m.decl, m.body,
                      llfn, impl_self(ty::node_id_to_type(cx.ccx.tcx, id)),
                      tps + m.tps, m.id);
           }
+          _ {
+            cx.ccx.tcx.sess.bug("Unbound id in trans_impl");
+          }
         }
     }
 }
@@ -148,6 +152,9 @@ fn trans_iface_callee(bcx: @block_ctxt, callee_id: ast::node_id,
                            T_opaque_cbox_ptr(bcx_ccx(bcx)));
     let iface_id = alt ty::struct(tcx, ty::expr_ty(tcx, base)) {
         ty::ty_iface(did, _) { did }
+        // precondition
+        _ { bcx_tcx(bcx).sess.span_bug(base.span, "base has non-iface type \
+             in trans_iface_callee"); }
     };
     trans_vtable_callee(bcx, self, dict, callee_id, iface_id, n_method)
 }
@@ -241,6 +248,10 @@ fn trans_impl_vtable(ccx: @crate_ctxt, pt: [ast::ident],
             let target = ccx.item_ids.get(m.id);
             trans_impl_wrapper(ccx, new_pt + [m.ident], extra_tps, target)
           }
+          _ {
+            ccx.tcx.sess.span_bug(it.span, "No matching method \
+               in trans_impl_vtable");
+          }
         }
     });
     let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
@@ -340,6 +351,10 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
                     d_params += [dict_param_dict(dict_id(tcx, origs[orig]))];
                     orig += 1u;
                   }
+                  _ {
+                    tcx.sess.bug("Someone forgot to document an invariant in \
+                      dict_id");
+                  }
                 }
             }
         }
@@ -348,6 +363,9 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
       typeck::dict_iface(did) {
         @{def: did, params: []}
       }
+      _ {
+        tcx.sess.bug("Unexpected dict_param in dict_id");
+      }
     }
 }
 
@@ -410,6 +428,9 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
       typeck::dict_iface(did) {
         {bcx: bcx, ptrs: [get_vtable(ccx, did)]}
       }
+      _ {
+        bcx_tcx(bcx).sess.bug("Unexpected dict_param in get_dict_ptrs");
+      }
     }
 }
 
diff --git a/src/comp/middle/trans/tvec.rs b/src/comp/middle/trans/tvec.rs
index 0b7df351d7a..7b4d0033ec8 100644
--- a/src/comp/middle/trans/tvec.rs
+++ b/src/comp/middle/trans/tvec.rs
@@ -1,6 +1,7 @@
 import vec;
 import option::none;
 import syntax::ast;
+import driver::session::session;
 import lib::llvm::llvm::{ValueRef, TypeRef};
 import back::abi;
 import base::{call_memmove, trans_shared_malloc, type_of_or_i8,
@@ -159,6 +160,10 @@ fn trans_append(cx: @block_ctxt, vec_ty: ty::t, lhsptr: ValueRef,
     let strings = alt ty::struct(bcx_tcx(cx), vec_ty) {
       ty::ty_str { true }
       ty::ty_vec(_) { false }
+      _ {
+          // precondition?
+          bcx_tcx(cx).sess.bug("Bad argument type in trans_append");
+      }
     };
 
     let {bcx: bcx, val: unit_sz} = size_of(cx, unit_ty);
@@ -230,7 +235,7 @@ fn trans_add(bcx: @block_ctxt, vec_ty: ty::t, lhs: ValueRef,
     let ccx = bcx_ccx(bcx);
     let strings = alt ty::struct(bcx_tcx(bcx), vec_ty) {
       ty::ty_str { true }
-      ty::ty_vec(_) { false }
+      _ { false }
     };
     let unit_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
     let llunitty = type_of_or_i8(bcx, unit_ty);
diff --git a/src/comp/middle/trans/uniq.rs b/src/comp/middle/trans/uniq.rs
index 8cff8794081..cca7e8a7399 100644
--- a/src/comp/middle/trans/uniq.rs
+++ b/src/comp/middle/trans/uniq.rs
@@ -74,6 +74,7 @@ fn content_ty(bcx: @block_ctxt, t: ty::t)
 
     alt ty::struct(bcx_tcx(bcx), t) {
       ty::ty_uniq({ty: ct, _}) { ct }
+      _ { std::util::unreachable(); }
     }
 }
 
diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs
index e1b0ccccad1..2934d4a5b1e 100644
--- a/src/comp/middle/tstate/auxiliary.rs
+++ b/src/comp/middle/tstate/auxiliary.rs
@@ -582,12 +582,14 @@ fn expr_to_constr_arg(tcx: ty::ctxt, e: @expr) -> @constr_arg_use {
             ret @respan(p.span,
                         carg_ident({ident: p.node.idents[0], node: id.node}));
           }
-          some(_) {
-            tcx.sess.bug("exprs_to_constr_args: non-local variable " +
-                             "as pred arg");
+          some(what) {
+              tcx.sess.span_bug(e.span,
+                 #fmt("exprs_to_constr_args: non-local variable %? \
+                                     as pred arg", what));
           }
           none {
-            tcx.sess.bug("exprs_to_constr_args: NONE " + "as pred arg");
+              tcx.sess.span_bug(e.span,
+                 "exprs_to_constr_args: unbound id as pred arg");
 
           }
         }
@@ -1055,10 +1057,8 @@ type binding = {lhs: [inst], rhs: option::t<initializer>};
 
 fn local_to_bindings(tcx: ty::ctxt, loc: @local) -> binding {
     let lhs = [];
-    pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p|
-            let ident = alt p.node
-               { pat_ident(name, _) { path_to_ident(name) } };
-        lhs += [{ident: ident, node: p.id}];
+    pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p_id, _s, name|
+        lhs += [{ident: path_to_ident(name), node: p_id}];
     };
     {lhs: lhs, rhs: loc.node.init}
 }
@@ -1070,7 +1070,7 @@ fn locals_to_bindings(tcx: ty::ctxt,
     ret rslt;
 }
 
-fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [ty::mode] {
+fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [mode] {
     let ty =
         ty::type_autoderef(fcx.ccx.tcx,
                            ty::node_id_to_type(fcx.ccx.tcx, callee));
@@ -1089,7 +1089,7 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> [ty::mode] {
 }
 
 fn callee_arg_init_ops(fcx: fn_ctxt, callee: node_id) -> [init_op] {
-    fn mode_to_op(m: ty::mode) -> init_op {
+    fn mode_to_op(m: mode) -> init_op {
         alt m { by_move { init_move } _ { init_assign } }
     }
     vec::map(callee_modes(fcx, callee), mode_to_op)
diff --git a/src/comp/middle/tstate/collect_locals.rs b/src/comp/middle/tstate/collect_locals.rs
index 30a93e4db36..1abc9903d5c 100644
--- a/src/comp/middle/tstate/collect_locals.rs
+++ b/src/comp/middle/tstate/collect_locals.rs
@@ -12,11 +12,9 @@ import aux::*;
 type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};
 
 fn collect_local(loc: @local, cx: ctxt, v: visit::vt<ctxt>) {
-    pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat)) {|p|
-            let ident = alt p.node
-                 { pat_ident(id, _) { path_to_ident(id) } };
-        log(debug, "collect_local: pushing " + ident);;
-        *cx.cs += [respan(loc.span, ninit(p.id, ident))];
+    pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat))
+     {|p_id, _s, id|
+       *cx.cs += [respan(loc.span, ninit(p_id, path_to_ident(id)))];
     };
     visit::visit_local(loc, cx, v);
 }
@@ -26,10 +24,6 @@ fn collect_pred(e: @expr, cx: ctxt, v: visit::vt<ctxt>) {
       expr_check(_, ch) { *cx.cs += [expr_to_constr(cx.tcx, ch)]; }
       expr_if_check(ex, _, _) { *cx.cs += [expr_to_constr(cx.tcx, ex)]; }
 
-
-
-
-
       // If it's a call, generate appropriate instances of the
       // call's constraints.
       expr_call(operator, operands, _) {
diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs
index 987bbb4d81d..9977b20cddb 100644
--- a/src/comp/middle/tstate/pre_post_conditions.rs
+++ b/src/comp/middle/tstate/pre_post_conditions.rs
@@ -18,7 +18,6 @@ import util::common::{new_def_hash, log_expr, field_exprs,
 import syntax::codemap::span;
 import driver::session::session;
 
-
 fn find_pre_post_mod(_m: _mod) -> _mod {
     #debug("implement find_pre_post_mod!");
     fail;
@@ -106,14 +105,12 @@ fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk,
                       id: node_id) {
     find_pre_post_expr(fcx, index);
     find_pre_post_block(fcx, body);
-    pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
-        let ident = alt p.node
-             { pat_ident(id, _) { path_to_ident(id) } };
-        let v_init = ninit(p.id, ident);
+    pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p_id, _s, n|
+        let v_init = ninit(p_id, path_to_ident(n));
         relax_precond_block(fcx, bit_num(fcx, v_init) as node_id, body);
         // Hack: for-loop index variables are frequently ignored,
         // so we pretend they're used
-        use_var(fcx, p.id);
+        use_var(fcx, p_id);
     };
 
     let loop_precond =
@@ -289,10 +286,10 @@ fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) {
     }
 }
 
-fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [ty::mode],
+fn forget_args_moved_in(fcx: fn_ctxt, parent: @expr, modes: [mode],
                         operands: [@expr]) {
     let i = 0u;
-    for mode: ty::mode in modes {
+    for mode: mode in modes {
         if mode == by_move {
             forget_in_postcond(fcx, parent.id, operands[i].id);
         }
@@ -571,8 +568,8 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                     /* LHS always becomes initialized,
                      whether or not this is a move */
                     find_pre_post_expr(fcx, an_init.expr);
-                    pat_bindings(alocal.node.pat) {|p|
-                        copy_pre_post(fcx.ccx, p.id, an_init.expr);
+                    pat_bindings(alocal.node.pat) {|p_id, _s, _n|
+                        copy_pre_post(fcx.ccx, p_id, an_init.expr);
                     };
                     /* Inherit ann from initializer, and add var being
                        initialized to the postcondition */
@@ -585,16 +582,12 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                     }
 
                     pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
-                        {|pat|
-                        /* FIXME: This won't be necessary when typestate
-                        works well enough for pat_bindings to return a
-                        refinement-typed thing. */
-                            let ident = alt pat.node
-                                     { pat_ident(n, _) { path_to_ident(n) } };
+                        {|p_id, _s, n|
+                        let ident = path_to_ident(n);
                         alt p {
                           some(p) {
                             copy_in_postcond(fcx, id,
-                                             {ident: ident, node: pat.id},
+                                             {ident: ident, node: p_id},
                                              {ident:
                                                   path_to_ident(p),
                                               node: an_init.expr.id},
@@ -602,7 +595,7 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                           }
                           none { }
                         }
-                        gen(fcx, id, ninit(pat.id, ident));
+                        gen(fcx, id, ninit(p_id, ident));
                     };
 
                     if an_init.op == init_move && is_path(an_init.expr) {
@@ -617,22 +610,16 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
                     /* Include the LHSs too, since those aren't in the
                      postconds of the RHSs themselves */
                     pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
-                        {|pat|
-                            // FIXME
-                            // Generalize this pattern? map_if_ident...
-                        alt pat.node {
-                          pat_ident(n, _) {
+                        {|pat_id, _s, n|
                             set_in_postcond(bit_num(fcx,
-                               ninit(pat.id, path_to_ident(n))), prev_pp);
-                          }
-                        }
-                    };
+                               ninit(pat_id, path_to_ident(n))), prev_pp);
+                          };
                     copy_pre_post_(fcx.ccx, id, prev_pp.precondition,
                                    prev_pp.postcondition);
                   }
                   none {
-                    pat_bindings(alocal.node.pat) {|p|
-                        clear_pp(node_id_to_ts_ann(fcx.ccx, p.id).conditions);
+                      pat_bindings(alocal.node.pat) {|p_id, _s, _n|
+                        clear_pp(node_id_to_ts_ann(fcx.ccx, p_id).conditions);
                     };
                     clear_pp(node_id_to_ts_ann(fcx.ccx, id).conditions);
                   }
diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs
index a125c00d63b..9a4bfc26ddf 100644
--- a/src/comp/middle/tstate/states.rs
+++ b/src/comp/middle/tstate/states.rs
@@ -215,6 +215,8 @@ fn find_pre_post_state_exprs(fcx: fn_ctxt, pres: prestate, id: node_id,
 
 fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
                             index: @expr, body: blk, id: node_id) -> bool {
+    // I'm confused about this -- how does the poststate for the body
+    // ever grow larger? It seems like it can't?
     let loop_pres = intersect_states(pres, block_poststate(fcx.ccx, body));
 
     let changed =
@@ -224,10 +226,9 @@ fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
     // Make sure the index vars are considered initialized
     // in the body
     let index_post = tritv_clone(expr_poststate(fcx.ccx, index));
-    pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
-        let ident = alt p.node
-           { pat_ident(name, _) { path_to_ident(name) } };
-        set_in_poststate_ident(fcx, p.id, ident, index_post);
+    pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat))
+      {|p_id, _s, n|
+       set_in_poststate_ident(fcx, p_id, path_to_ident(n), index_post);
     };
 
     changed |= find_pre_post_state_block(fcx, index_post, body);
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 57031e7c6da..597fd548f04 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -42,6 +42,7 @@ export fold_ty;
 export field;
 export field_idx;
 export get_field;
+export get_fields;
 export fm_general;
 export get_element_type;
 export idx_nil;
@@ -84,7 +85,6 @@ export mk_var;
 export mk_opaque_closure_ptr;
 export mk_named;
 export gen_ty;
-export mode;
 export mt;
 export node_type_table;
 export pat_ty;
@@ -125,7 +125,6 @@ export ty_ptr;
 export ty_rec;
 export ty_enum;
 export ty_tup;
-export ty_type;
 export ty_send_type;
 export ty_uint;
 export ty_uniq;
@@ -177,7 +176,6 @@ export variant_info;
 export walk_ty;
 export occurs_check_fails;
 export closure_kind;
-export ck_any;
 export ck_block;
 export ck_box;
 export ck_uniq;
@@ -186,7 +184,10 @@ export param_bounds_to_kind;
 
 // Data types
 
-type arg = {mode: mode, ty: t};
+// TODO: really should be a separate type, or a refinement,
+// so that we don't have to handle the mode_infer case after
+// typeck. but that's too hard right now.
+type arg = {mode: ast::mode, ty: t};
 
 type field = {ident: ast::ident, mt: mt};
 
@@ -232,7 +233,6 @@ type raw_t = {struct: sty,
 type t = uint;
 
 enum closure_kind {
-    ck_any,
     ck_block,
     ck_box,
     ck_uniq,
@@ -458,7 +458,7 @@ fn mk_raw_ty(cx: ctxt, st: sty) -> @raw_t {
     }
     alt st {
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_str | ty_send_type | ty_type | ty_native(_) |
+      ty_str | ty_type | ty_send_type | ty_native(_) |
       ty_opaque_closure_ptr(_) {
         /* no-op */
       }
@@ -629,7 +629,7 @@ pure fn struct_raw(cx: ctxt, typ: t) -> sty {
     interner::get(*cx.ts, typ).struct
 }
 
-// Returns struact(cx, typ) but replaces all occurences of platform
+// Returns struct(cx, typ) but replaces all occurences of platform
 // dependent primitive types with their machine type equivalent
 pure fn mach_struct(cx: ctxt, cfg: @session::config, typ: t) -> sty {
     alt interner::get(*cx.ts, typ).struct {
@@ -678,6 +678,9 @@ fn walk_ty(cx: ctxt, ty: t, f: fn(t)) {
       }
       ty_constr(sub, _) { walk_ty(cx, sub, f); }
       ty_uniq(tm) { walk_ty(cx, tm.ty, f); }
+      // precondition?
+      ty_named(_,_) { cx.sess.bug("walk_ty: should not see a ty_named \
+                        here"); }
     }
     f(ty);
 }
@@ -699,7 +702,7 @@ fn fold_ty(cx: ctxt, fld: fold_mode, ty_0: t) -> t {
     }
     alt interner::get(*cx.ts, ty).struct {
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_str | ty_send_type | ty_type | ty_native(_) |
+      ty_str | ty_type | ty_send_type | ty_native(_) |
       ty_opaque_closure_ptr(_) {
         /* no-op */
       }
@@ -1033,6 +1036,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
           param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
       }
       ty_constr(t, _) { type_kind(cx, t) }
+      _ { cx.sess.bug("Bad type in type_kind"); }
     };
 
     cx.kind_cache.insert(ty, result);
@@ -1192,9 +1196,14 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
       }
       ty_constr(subt, _) { result = type_is_pod(cx, subt); }
       ty_var(_) {
-        fail "ty_var in type_is_pod";
+          cx.sess.bug("ty_var in type_is_pod");
       }
       ty_param(_, _) { result = false; }
+      ty_opaque_closure_ptr(_) { result = true; }
+      ty_named(_,_) {
+          cx.sess.bug("ty_named in type_is_pod");
+      }
+
     }
 
     ret result;
@@ -1577,12 +1586,17 @@ fn field_idx(id: ast::ident, fields: [field]) -> option::t<uint> {
 }
 
 fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
+    alt vec::find(get_fields(tcx, rec_ty), {|f| str::eq(f.ident, id) }) {
+         some(f) { ret f; }
+         _ { tcx.sess.bug(#fmt("get_field: bad field id %s", id)); }
+    }
+}
+
+// TODO: could have a precondition instead of failing
+fn get_fields(tcx:ctxt, rec_ty:t) -> [field] {
     alt struct(tcx, rec_ty) {
-      ty_rec(fields) {
-        alt vec::find(fields, {|f| str::eq(f.ident, id) }) {
-            some(f) { ret f; }
-        }
-      }
+       ty::ty_rec(fields) { fields }
+       _ { tcx.sess.bug("get_fields called on non-record type"); }
     }
 }
 
@@ -1669,6 +1683,8 @@ mod unify {
              variance: variance) -> union_result {
         let vb = alt cx.st {
             in_bindings(vb) { vb }
+            _ { cx.tcx.sess.bug("Someone forgot to document an invariant \
+                         in union"); }
         };
         ufind::grow(vb.sets, math::max(set_a, set_b) + 1u);
         let root_a = ufind::find(vb.sets, set_a);
@@ -1719,7 +1735,10 @@ mod unify {
     fn record_var_binding(
         cx: @ctxt, key: int, typ: t, variance: variance) -> result {
 
-        let vb = alt cx.st { in_bindings(vb) { vb } };
+        let vb = alt cx.st { in_bindings(vb) { vb }
+            _ { cx.tcx.sess.bug("Someone forgot to document an invariant \
+                 in record_var_binding");  }
+        };
         ufind::grow(vb.sets, (key as uint) + 1u);
         let root = ufind::find(vb.sets, key as uint);
         let result_type = typ;
@@ -2060,7 +2079,7 @@ mod unify {
             ret ures_ok(actual);
           }
           ty::ty_bool | ty::ty_int(_) | ty_uint(_) | ty_float(_) |
-          ty::ty_str | ty::ty_type | ty::ty_send_type {
+          ty::ty_str | ty::ty_send_type {
             ret struct_cmp(cx, expected, actual);
           }
           ty::ty_native(ex_id) {
@@ -2333,6 +2352,7 @@ mod unify {
               }
             }
           }
+          _ { cx.tcx.sess.bug("unify: unexpected type"); }
         }
     }
     fn unify(expected: t, actual: t, st: unify_style,
@@ -2497,6 +2517,7 @@ fn def_has_ty_params(def: ast::def) -> bool {
       ast::def_ty_param(_, _) | ast::def_binding(_) | ast::def_use(_) |
       ast::def_native_ty(_) | ast::def_self(_) | ast::def_ty(_) { false }
       ast::def_fn(_, _) | ast::def_variant(_, _) { true }
+      _ { false } // ????
     }
 }
 
@@ -2552,6 +2573,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
                     // FIXME: issue #1417
                     disr_val = alt syntax::ast_util::eval_const_expr(ex) {
                       ast_util::const_int(val) {val as int}
+                      _ { cx.sess.bug("tag_variants: bad disr expr"); }
                     }
                   }
                   _ {disr_val += 1;}
@@ -2564,6 +2586,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
                  }
             })
           }
+          _ { cx.sess.bug("tag_variants: id not bound to an enum"); }
         }
     };
     cx.enum_var_cache.insert(id, result);
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index de467009750..da951150c7f 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -107,6 +107,9 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
           some(self_impl(impl_t)) {
             ret {bounds: @[], ty: impl_t};
           }
+          none {
+              fcx.ccx.tcx.sess.span_bug(sp, "def_self with no self_info");
+          }
         }
       }
       ast::def_fn(id, _) | ast::def_const(id) |
@@ -248,16 +251,14 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
                   some(ast_map::node_native_item(native_item)) {
                     ty_of_native_item(tcx, mode, native_item)
                   }
+                  _ {
+                    tcx.sess.bug("Unexpected sort of item in ast_ty_to_ty");
+                  }
                 }
             }
           }
         }
     }
-    fn ast_arg_to_arg(tcx: ty::ctxt, mode: mode, arg: ast::arg)
-        -> {mode: ty::mode, ty: ty::t} {
-        let ty = ast_ty_to_ty(tcx, mode, arg.ty);
-        ret {mode: default_arg_mode_for_ty(tcx, arg.mode, ty), ty: ty};
-    }
     alt tcx.ast_ty_to_ty_cache.find(ast_ty) {
       some(some(ty)) { ret ty; }
       some(none) {
@@ -364,6 +365,10 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
                                 "found `ty_infer` in unexpected place"); }
         }
       }
+      ast::ty_mac(_) {
+          tcx.sess.span_bug(ast_ty.span,
+                                "found `ty_mac` in unexpected place");
+      }
     }
     tcx.ast_ty_to_ty_cache.insert(ast_ty, some(typ));
     ret typ;
@@ -587,7 +592,13 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, impl_m: ty::method,
         tcx.sess.span_err(sp, "method `" + if_m.ident +
                           "` has an incompatible set of type parameters");
     } else {
-        let impl_fty = ty::mk_fn(tcx, impl_m.fty);
+        let auto_modes = vec::map2(impl_m.fty.inputs, if_m.fty.inputs, {|i, f|
+            alt ty::struct(tcx, f.ty) {
+              ty::ty_param(0u, _) { {mode: ast::by_ref with i} }
+              _ { i }
+            }
+        });
+        let impl_fty = ty::mk_fn(tcx, {inputs: auto_modes with impl_m.fty});
         // Add dummy substs for the parameters of the impl method
         let substs = substs + vec::init_fn(vec::len(*if_m.tps), {|i|
             ty::mk_param(tcx, i + impl_tps, {crate: 0, node: 0})
@@ -1209,7 +1220,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
         // Typecheck the path.
         let v_def = lookup_def(fcx, path.span, pat.id);
         let v_def_ids = ast_util::variant_def_ids(v_def);
-        let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.tg);
+        let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
         instantiate_path(fcx, path, ctor_tpt, pat.span, pat.id);
 
         // Take the enum type params out of `expected`.
@@ -1422,6 +1433,9 @@ fn impl_self_ty(tcx: ty::ctxt, did: ast::def_id) -> {n_tps: uint, ty: ty::t} {
                                _}) {
             {n_tps: vec::len(ts), ty: ast_ty_to_ty(tcx, m_check, st)}
           }
+          an_item {
+              tcx.sess.bug("Undocumented invariant in impl_self_ty");
+          }
         }
     } else {
         let tpt = csearch::get_type(tcx, did);
@@ -1444,6 +1458,10 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
               ty::bound_iface(t) {
                 let (iid, tps) = alt ty::struct(tcx, t) {
                     ty::ty_iface(i, tps) { (i, tps) }
+                    _ {
+                        tcx.sess.span_bug(sp, "Undocument invariant in \
+                          lookup_method");
+                    }
                 };
                 let ifce_methods = ty::iface_methods(tcx, iid);
                 alt vec::position_pred(*ifce_methods, {|m| m.ident == name}) {
@@ -1485,6 +1503,9 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes,
                 let mt = ty_of_method(tcx, m_check, m);
                 ty::mk_fn(tcx, mt.fty)
               }
+              _ {
+                  tcx.sess.bug("Undocumented invariant in ty_from_did");
+              }
             }
         } else { csearch::get_type(tcx, did).ty }
     }
@@ -1793,7 +1814,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
 
         let rhs_bot = check_expr_with(fcx, rhs, lhs_t);
         if !ast_util::lazy_binop(binop) { bot |= rhs_bot; }
-
         let result = check_binop(fcx, expr, lhs_t, binop, rhs);
         write_ty(tcx, id, result);
       }
@@ -2335,6 +2355,8 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
         let id_map = pat_util::pat_id_map(fcx.ccx.tcx, local.node.pat);
         check_pat(fcx, id_map, local.node.pat, t);
       }
+      _ { fcx.ccx.tcx.sess.span_bug(local.span, "Undocumented invariant \
+            in check_decl_local");  }
     }
     ret bot;
 }
@@ -2697,7 +2719,7 @@ fn arg_is_argv_ty(tcx: ty::ctxt, a: ty::arg) -> bool {
     }
 }
 
-fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
+fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id, main_span: span) {
     let main_t = ty::node_id_to_type(tcx, main_id);
     alt ty::struct(tcx, main_t) {
       ty::ty_fn({proto: ast::proto_bare, inputs, output,
@@ -2708,15 +2730,13 @@ fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
         ok &= num_args == 0u || num_args == 1u &&
               arg_is_argv_ty(tcx, inputs[0]);
         if !ok {
-            let span = ast_map::node_span(tcx.items.get(main_id));
-            tcx.sess.span_err(span,
+            tcx.sess.span_err(main_span,
                               "wrong type in main function: found `" +
                                   ty_to_str(tcx, main_t) + "`");
         }
       }
       _ {
-        let span = ast_map::node_span(tcx.items.get(main_id));
-        tcx.sess.span_bug(span,
+        tcx.sess.span_bug(main_span,
                           "main has a non-function type: found `" +
                               ty_to_str(tcx, main_t) + "`");
       }
@@ -2726,7 +2746,7 @@ fn check_main_fn_ty(tcx: ty::ctxt, main_id: ast::node_id) {
 fn check_for_main_fn(tcx: ty::ctxt, crate: @ast::crate) {
     if !tcx.sess.building_library {
         alt tcx.sess.main_fn {
-          some(id) { check_main_fn_ty(tcx, id); }
+          some((id, sp)) { check_main_fn_ty(tcx, id, sp); }
           none { tcx.sess.span_err(crate.span, "main function not found"); }
         }
     }
@@ -2765,6 +2785,8 @@ mod dict {
         let tcx = fcx.ccx.tcx;
         let (iface_id, iface_tps) = alt ty::struct(tcx, iface_ty) {
             ty::ty_iface(did, tps) { (did, tps) }
+            _ { tcx.sess.span_bug(sp, "Undocumented invariant in lookup\
+                 _dict"); }
         };
         let ty = fixup_ty(fcx, sp, ty);
         alt ty::struct(tcx, ty) {
@@ -2777,6 +2799,8 @@ mod dict {
                       ty::ty_iface(idid, _) {
                         if iface_id == idid { ret dict_param(n, n_bound); }
                       }
+                      _ { tcx.sess.span_bug(sp, "Undocumented invariant in \
+                           lookup_dict"); }
                     }
                     n_bound += 1u;
                   }
@@ -2796,6 +2820,9 @@ mod dict {
                       some(ity) {
                         alt ty::struct(tcx, ity) {
                           ty::ty_iface(id, _) { id == iface_id }
+                          // Bleah, abstract this
+                          _ { tcx.sess.span_bug(sp, "Undocumented invariant \
+                               in lookup_dict"); }
                         }
                       }
                       _ { false }
@@ -2862,6 +2889,10 @@ mod dict {
             vec::iter2(tps, iface_tys,
                        {|a, b| demand::simple(fcx, sp, a, b);});
           }
+          _ {
+              tcx.sess.span_bug(sp, "Undocumented invariant in \
+                 connect_iface_tps");
+          }
         }
     }
 
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs
index 1436f9b08f4..f52afc0875c 100644
--- a/src/comp/syntax/ast.rs
+++ b/src/comp/syntax/ast.rs
@@ -328,14 +328,10 @@ enum ty_ {
     ty_uniq(mt),
     ty_vec(mt),
     ty_ptr(mt),
-    ty_task,
-    ty_port(@ty),
-    ty_chan(@ty),
     ty_rec([ty_field]),
     ty_fn(proto, fn_decl),
     ty_tup([@ty]),
     ty_path(@path, node_id),
-    ty_type,
     ty_constr(@ty, [@ty_constr]),
     ty_mac(mac),
     // ty_infer means the type should be inferred instead of it having been
diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs
index 68b157cecb8..baaa3022eb3 100644
--- a/src/comp/syntax/ast_util.rs
+++ b/src/comp/syntax/ast_util.rs
@@ -19,8 +19,10 @@ fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
 
 fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }
 
-fn variant_def_ids(d: def) -> {tg: def_id, var: def_id} {
-    alt d { def_variant(enum_id, var_id) { ret {tg: enum_id, var: var_id}; } }
+fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
+    alt d { def_variant(enum_id, var_id) {
+            ret {enm: enum_id, var: var_id}; }
+        _ { fail "non-variant in variant_def_ids"; } }
 }
 
 fn def_id_of_def(d: def) -> def_id {
@@ -77,6 +79,7 @@ fn is_path(e: @expr) -> bool {
 
 fn int_ty_to_str(t: int_ty) -> str {
     alt t {
+      ty_char { "u8" } // ???
       ty_i { "" } ty_i8 { "i8" } ty_i16 { "i16" }
       ty_i32 { "i32" } ty_i64 { "i64" }
     }
@@ -86,7 +89,7 @@ fn int_ty_max(t: int_ty) -> u64 {
     alt t {
       ty_i8 { 0x80u64 }
       ty_i16 { 0x800u64 }
-      ty_char | ty_i32 { 0x80000000u64 }
+      ty_i | ty_char | ty_i32 { 0x80000000u64 } // actually ni about ty_i
       ty_i64 { 0x8000000000000000u64 }
     }
 }
@@ -102,7 +105,7 @@ fn uint_ty_max(t: uint_ty) -> u64 {
     alt t {
       ty_u8 { 0xffu64 }
       ty_u16 { 0xffffu64 }
-      ty_u32 { 0xffffffffu64 }
+      ty_u | ty_u32 { 0xffffffffu64 } // actually ni about ty_u
       ty_u64 { 0xffffffffffffffffu64 }
     }
 }
@@ -223,12 +226,14 @@ fn eval_const_expr(e: @expr) -> const_val {
           const_float(f) { const_float(-f) }
           const_int(i) { const_int(-i) }
           const_uint(i) { const_uint(-i) }
+          _ { fail "eval_const_expr: bad neg argument"; }
         }
       }
       expr_unary(not, inner) {
         alt eval_const_expr(inner) {
           const_int(i) { const_int(!i) }
           const_uint(i) { const_uint(!i) }
+          _ { fail "eval_const_expr: bad not argument"; }
         }
       }
       expr_binary(op, a, b) {
@@ -240,6 +245,7 @@ fn eval_const_expr(e: @expr) -> const_val {
               rem { const_float(a % b) } eq { fromb(a == b) }
               lt { fromb(a < b) } le { fromb(a <= b) } ne { fromb(a != b) }
               ge { fromb(a >= b) } gt { fromb(a > b) }
+              _ { fail "eval_const_expr: can't apply this binop to floats"; }
             }
           }
           (const_int(a), const_int(b)) {
@@ -253,6 +259,7 @@ fn eval_const_expr(e: @expr) -> const_val {
               eq { fromb(a == b) } lt { fromb(a < b) }
               le { fromb(a <= b) } ne { fromb(a != b) }
               ge { fromb(a >= b) } gt { fromb(a > b) }
+              _ { fail "eval_const_expr: can't apply this binop to ints"; }
             }
           }
           (const_uint(a), const_uint(b)) {
@@ -267,11 +274,17 @@ fn eval_const_expr(e: @expr) -> const_val {
               eq { fromb(a == b) } lt { fromb(a < b) }
               le { fromb(a <= b) } ne { fromb(a != b) }
               ge { fromb(a >= b) } gt { fromb(a > b) }
+              _ { fail "eval_const_expr: can't apply this binop to uints"; }
             }
           }
+          _ { fail "eval_constr_expr: bad binary arguments"; }
         }
       }
       expr_lit(lit) { lit_to_const(lit) }
+      // Precondition?
+      _ {
+          fail "eval_const_expr: non-constant expression";
+      }
     }
 }
 
@@ -324,6 +337,9 @@ fn compare_const_vals(a: const_val, b: const_val) -> int {
             1
         }
     }
+    _ {
+        fail "compare_const_vals: ill-typed comparison";
+    }
   }
 }
 
@@ -341,6 +357,17 @@ fn ident_to_path(s: span, i: ident) -> @path {
     @respan(s, {global: false, idents: [i], types: []})
 }
 
+pure fn is_unguarded(&&a: arm) -> bool {
+    alt a.guard {
+      none { true }
+      _    { false }
+    }
+}
+
+pure fn unguarded_pat(a: arm) -> option::t<[@pat]> {
+    if is_unguarded(a) { some(a.pats) } else { none }
+}
+
 // Provides an extra node_id to hang callee information on, in case the
 // operator is deferred to a user-supplied method. The parser is responsible
 // for reserving this id.
diff --git a/src/comp/syntax/ext/simplext.rs b/src/comp/syntax/ext/simplext.rs
index 5477c495883..b7fdfc46908 100644
--- a/src/comp/syntax/ext/simplext.rs
+++ b/src/comp/syntax/ext/simplext.rs
@@ -4,6 +4,7 @@ import codemap::span;
 import core::{vec, option};
 import std::map::{hashmap, new_str_hash};
 import option::{some, none};
+import driver::session::session;
 
 import base::{ext_ctxt, normal};
 
@@ -460,11 +461,6 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) {
               }
             }
           }
-
-
-
-
-
           /* TODO: handle embedded types and blocks, at least */
           expr_mac(mac) {
             p_t_s_r_mac(cx, mac, s, b);
@@ -483,6 +479,9 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) {
           }
         }
       }
+      _ {
+          cx.session().bug("undocumented invariant in p_t_s_rec");
+      }
     }
 }
 
@@ -718,6 +717,10 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: @expr,
                     // FIXME: check duplicates (or just simplify
                     // the macro arg situation)
                   }
+                  _ {
+                      cx.span_bug(mac.span, "undocumented invariant in \
+                         add_extension");
+                  }
                 }
               }
               _ {
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 1c81eda7df5..95c37b9b8e9 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -258,7 +258,7 @@ fn check_bad_word(p: parser) {
     }
 }
 
-fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
+fn parse_ty_fn(p: parser) -> ast::fn_decl {
     fn parse_fn_input_ty(p: parser) -> ast::arg {
         let mode = parse_arg_mode(p);
         let name = if is_plain_ident(p) && p.look_ahead(1u) == token::COLON {
@@ -275,9 +275,9 @@ fn parse_ty_fn(proto: ast::proto, p: parser) -> ast::ty_ {
     //  auto constrs = parse_constrs(~[], p);
     let constrs: [@ast::constr] = [];
     let (ret_style, ret_ty) = parse_ret_ty(p);
-    ret ast::ty_fn(proto, {inputs: inputs.node, output: ret_ty,
+    ret {inputs: inputs.node, output: ret_ty,
                            purity: ast::impure_fn, cf: ret_style,
-                           constraints: constrs});
+                           constraints: constrs};
 }
 
 fn parse_ty_methods(p: parser) -> [ast::ty_method] {
@@ -287,15 +287,10 @@ fn parse_ty_methods(p: parser) -> [ast::ty_method] {
         expect_word(p, "fn");
         let ident = parse_method_name(p);
         let tps = parse_ty_params(p);
-        let f = parse_ty_fn(ast::proto_bare, p), fhi = p.last_span.hi;
+        let d = parse_ty_fn(p), fhi = p.last_span.hi;
         expect(p, token::SEMI);
-        alt f {
-          ast::ty_fn(_, d) {
             {ident: ident, attrs: attrs, decl: d, tps: tps,
-             span: ast_util::mk_sp(flo, fhi)}
-          }
-        }
-    }, p).node
+                    span: ast_util::mk_sp(flo, fhi)}}, p).node
 }
 
 fn parse_mt(p: parser) -> ast::mt {
@@ -506,10 +501,10 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
           ast::proto_bare { p.warn("fn is deprecated, use native fn"); }
           _ { /* fallthrough */ }
         }
-        t = parse_ty_fn(proto, p);
+        t = ast::ty_fn(proto, parse_ty_fn(p));
     } else if eat_word(p, "native") {
         expect_word(p, "fn");
-        t = parse_ty_fn(ast::proto_bare, p);
+        t = ast::ty_fn(ast::proto_bare, parse_ty_fn(p));
     } else if p.token == token::MOD_SEP || is_ident(p.token) {
         let path = parse_path(p);
         t = ast::ty_path(path, p.get_id());
diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs
index c361beb21ce..fbfa5f4f433 100644
--- a/src/comp/syntax/print/pprust.rs
+++ b/src/comp/syntax/print/pprust.rs
@@ -336,17 +336,6 @@ fn print_type(s: ps, &&ty: @ast::ty) {
         word(s.s, "]");
       }
       ast::ty_ptr(mt) { word(s.s, "*"); print_mt(s, mt); }
-      ast::ty_task { word(s.s, "task"); }
-      ast::ty_port(t) {
-        word(s.s, "port<");
-        print_type(s, t);
-        word(s.s, ">");
-      }
-      ast::ty_chan(t) {
-        word(s.s, "chan<");
-        print_type(s, t);
-        word(s.s, ">");
-      }
       ast::ty_rec(fields) {
         word(s.s, "{");
         fn print_field(s: ps, f: ast::ty_field) {
@@ -370,12 +359,18 @@ fn print_type(s: ps, &&ty: @ast::ty) {
         print_ty_fn(s, some(proto), d, none, none);
       }
       ast::ty_path(path, _) { print_path(s, path, false); }
-      ast::ty_type { word(s.s, "type"); }
       ast::ty_constr(t, cs) {
         print_type(s, t);
         space(s.s);
         word(s.s, ast_ty_constrs_str(cs));
       }
+      ast::ty_mac(_) {
+          fail "print_type doesn't know how to print a ty_mac";
+      }
+      ast::ty_infer {
+          fail "print_type shouldn't see a ty_infer";
+      }
+
     }
     end(s);
 }
@@ -703,11 +698,6 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
         alt els {
           some(_else) {
             alt _else.node {
-
-
-
-
-
               // "another else-if"
               ast::expr_if(i, t, e) {
                 cbox(s, indent_unit - 1u);
@@ -718,11 +708,6 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
                 print_block(s, t);
                 do_else(s, e);
               }
-
-
-
-
-
               // "final else"
               ast::expr_block(b) {
                 cbox(s, indent_unit - 1u);
@@ -730,6 +715,10 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
                 word(s.s, " else ");
                 print_block(s, b);
               }
+              // BLEAH, constraints would be great here
+              _ {
+                  fail "print_if saw if with weird alternative";
+              }
             }
           }
           _ {/* fall through */ }
diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs
index 1fb6991256e..2ba0567c213 100644
--- a/src/comp/syntax/visit.rs
+++ b/src/comp/syntax/visit.rs
@@ -165,7 +165,6 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
         v.visit_ty(decl.output, e, v);
       }
       ty_path(p, _) { visit_path(p, e, v); }
-      ty_type {/* no-op */ }
       ty_constr(t, cs) {
         v.visit_ty(t, e, v);
         for tc: @spanned<constr_general_<@path, node_id>> in cs {
diff --git a/src/comp/util/ppaux.rs b/src/comp/util/ppaux.rs
index dd563048293..9b0be29ca26 100644
--- a/src/comp/util/ppaux.rs
+++ b/src/comp/util/ppaux.rs
@@ -8,7 +8,7 @@ import syntax::print::pprust::{path_to_str, constr_args_to_str, proto_to_str};
 import syntax::{ast, ast_util};
 import middle::ast_map;
 
-fn mode_str(m: ty::mode) -> str {
+fn mode_str(m: ast::mode) -> str {
     alt m {
       ast::by_ref { "&&" }
       ast::by_val { "++" }
@@ -20,7 +20,7 @@ fn mode_str(m: ty::mode) -> str {
 }
 
 fn ty_to_str(cx: ctxt, typ: t) -> str {
-    fn fn_input_to_str(cx: ctxt, input: {mode: middle::ty::mode, ty: t}) ->
+    fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
        str {
         let modestr = alt input.mode {
           ast::by_ref {