diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 9223eaaa121..b562805e8d9 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3660,7 +3660,8 @@ fn join_results(&@block_ctxt parent_cx,
 }
 
 fn trans_if(&@block_ctxt cx, &@ast::expr cond,
-            &ast::block thn, &option::t[@ast::expr] els) -> result {
+            &ast::block thn, &option::t[@ast::expr] els,
+            &ast::ann ann) -> result {
 
     auto cond_res = trans_expr(cx, cond);
 
@@ -3699,12 +3700,12 @@ fn trans_if(&@block_ctxt cx, &@ast::expr cond,
             // If we have an else expression, then the entire
             // if expression can have a non-nil type.
             // FIXME: This isn't quite right, particularly re: dynamic types
-            auto expr_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, elexpr);
+            auto expr_ty = ty::ann_to_type(cx.fcx.lcx.ccx.tcx.node_types,
+                                           ann);
             if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, expr_ty)) {
                 expr_llty = T_typaram_ptr(cx.fcx.lcx.ccx.tn);
             } else {
-                expr_llty = type_of(else_res.bcx.fcx.lcx.ccx, elexpr.span,
-                                    expr_ty);
+                expr_llty = type_of(cx.fcx.lcx.ccx, elexpr.span, expr_ty);
                 if (ty::type_is_structural(cx.fcx.lcx.ccx.tcx, expr_ty)) {
                     expr_llty = T_ptr(expr_llty);
                 }
@@ -5392,8 +5393,8 @@ fn trans_expr(&@block_ctxt cx, &@ast::expr e) -> result {
             ret trans_binary(cx, op, x, y);
         }
 
-        case (ast::expr_if(?cond, ?thn, ?els, _)) {
-            ret trans_if(cx, cond, thn, els);
+        case (ast::expr_if(?cond, ?thn, ?els, ?ann)) {
+            ret trans_if(cx, cond, thn, els, ann);
         }
 
         case (ast::expr_for(?decl, ?seq, ?body, _)) {
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index aedbb89f2a8..a679804e0b6 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -1331,12 +1331,19 @@ mod Pushdown {
             case (ast::expr_if(?cond, ?then_0, ?else_0, ?ann)) {
                 auto t = Demand::autoderef(scx, e.span, expected,
                     ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
-                pushdown_block(scx, expected, then_0);
+
+                auto then_t = ty::block_ty(scx.fcx.ccx.tcx, then_0);
+                if (!ty::type_is_bot(scx.fcx.ccx.tcx, then_t)) {
+                    pushdown_block(scx, expected, then_0);
+                }
 
                 alt (else_0) {
                     case (none[@ast::expr]) { /* no-op */ }
                     case (some[@ast::expr](?e_0)) {
-                        pushdown_expr(scx, expected, e_0);
+                        auto else_t = ty::expr_ty(scx.fcx.ccx.tcx, e_0);
+                        if (!ty::type_is_bot(scx.fcx.ccx.tcx, else_t)) {
+                            pushdown_expr(scx, expected, e_0);
+                        }
                     }
                 }
                 write::ty_only_fixup(scx, ann.id, t);
@@ -2129,21 +2136,30 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
             check_block(scx, thn);
             auto thn_t = block_ty(scx.fcx.ccx.tcx, thn);
 
-            auto elsopt_t;
+            auto if_t;
             alt (elsopt) {
                 case (some[@ast::expr](?els)) {
                     check_expr(scx, els);
-                    Pushdown::pushdown_expr(scx, thn_t, els);
-                    elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
+                    auto elsopt_t = expr_ty(scx.fcx.ccx.tcx, els);
+                    if (!ty::type_is_bot(scx.fcx.ccx.tcx, elsopt_t)) {
+                        Pushdown::pushdown_expr(scx, thn_t, els);
+                        if_t = elsopt_t;
+                    } else if (!ty::type_is_bot(scx.fcx.ccx.tcx, thn_t)) {
+                        if_t = thn_t;
+                    } else {
+                        if_t = ty::mk_nil(scx.fcx.ccx.tcx);
+                    }
                 }
                 case (none[@ast::expr]) {
-                    elsopt_t = ty::mk_nil(scx.fcx.ccx.tcx);
+                    if_t = ty::mk_nil(scx.fcx.ccx.tcx);
                 }
             }
 
-            Pushdown::pushdown_block(scx, elsopt_t, thn);
+            if (!ty::type_is_bot(scx.fcx.ccx.tcx, thn_t)) {
+                Pushdown::pushdown_block(scx, if_t, thn);
+            }
 
-            write::ty_only_fixup(scx, a.id, elsopt_t);
+            write::ty_only_fixup(scx, a.id, if_t);
         }
 
         case (ast::expr_for(?decl, ?seq, ?body, ?a)) {
diff --git a/src/test/run-fail/expr-if-fail.rs b/src/test/run-fail/expr-if-fail.rs
new file mode 100644
index 00000000000..2a4f6d27a4c
--- /dev/null
+++ b/src/test/run-fail/expr-if-fail.rs
@@ -0,0 +1,12 @@
+// xfail-stage0
+// error-pattern:explicit failure
+
+fn main() {
+  auto x = if (false) {
+    0
+  } else if (true) {
+    fail
+  } else {
+    10
+  };
+}
diff --git a/src/test/run-pass/expr-if-fail.rs b/src/test/run-pass/expr-if-fail.rs
new file mode 100644
index 00000000000..189f8a72469
--- /dev/null
+++ b/src/test/run-pass/expr-if-fail.rs
@@ -0,0 +1,36 @@
+// xfail-stage0
+
+fn test_if_fail() {
+  auto x = if (false) {
+    fail
+  } else {
+    10
+  };
+  assert (x == 10);
+}
+
+fn test_else_fail() {
+  auto x = if (true) {
+    10
+  } else {
+    fail
+  };
+  assert (x == 10);
+}
+
+fn test_elseif_fail() {
+  auto x = if (false) {
+    0
+  } else if (false) {
+    fail
+  } else {
+    10
+  };
+  assert (x == 10);
+}
+
+fn main() {
+  test_if_fail();
+  test_else_fail();
+  test_elseif_fail();
+}