about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-01-08 06:21:19 -0800
committerNiko Matsakis <niko@alum.mit.edu>2013-01-08 14:21:06 -0800
commit9f7dc1cb33599ea3c6b7e554e36888e8b20441b5 (patch)
treeddb6626367948f127e52209e6874d31434ce67c7
parent80435ad429429ae0e5e9c5c131e4719306bd50fa (diff)
downloadrust-9f7dc1cb33599ea3c6b7e554e36888e8b20441b5.tar.gz
rust-9f7dc1cb33599ea3c6b7e554e36888e8b20441b5.zip
Remove ret_style and instead check whether fn return type is bot
cc #3681
-rw-r--r--src/librustc/metadata/tydecode.rs12
-rw-r--r--src/librustc/metadata/tyencode.rs5
-rw-r--r--src/librustc/middle/lint.rs26
-rw-r--r--src/librustc/middle/trans/base.rs11
-rw-r--r--src/librustc/middle/trans/foreign.rs3
-rw-r--r--src/librustc/middle/trans/monomorphize.rs6
-rw-r--r--src/librustc/middle/trans/reflect.rs6
-rw-r--r--src/librustc/middle/ty.rs34
-rw-r--r--src/librustc/middle/typeck/astconv.rs3
-rw-r--r--src/librustc/middle/typeck/check/mod.rs9
-rw-r--r--src/librustc/middle/typeck/collect.rs12
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs5
-rw-r--r--src/librustc/middle/typeck/infer/glb.rs12
-rw-r--r--src/librustc/middle/typeck/infer/lub.rs8
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs6
-rw-r--r--src/librustc/middle/typeck/infer/test.rs3
-rw-r--r--src/librustc/util/ppaux.rs35
-rw-r--r--src/test/compile-fail/bad-bang-ann-3.rs2
-rw-r--r--src/test/compile-fail/bad-bang-ann.rs2
-rw-r--r--src/test/compile-fail/bang-tailexpr.rs2
-rw-r--r--src/test/compile-fail/closure-that-fails.rs7
-rw-r--r--src/test/compile-fail/issue-897-2.rs2
-rw-r--r--src/test/compile-fail/issue-897.rs2
-rw-r--r--src/test/compile-fail/loop-does-not-diverge.rs2
24 files changed, 70 insertions, 145 deletions
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 38bfaa98566..089e528c0c2 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -90,13 +90,6 @@ fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
     parse_arg(st, conv)
 }
 
-fn parse_ret_ty(st: @pstate, conv: conv_did) -> (ast::ret_style, ty::t) {
-    match peek(st) {
-      '!' => { next(st); (ast::noreturn, ty::mk_bot(st.tcx)) }
-      _ => (ast::return_val, parse_ty(st, conv))
-    }
-}
-
 fn parse_path(st: @pstate) -> @ast::path {
     let mut idents: ~[ast::ident] = ~[];
     fn is_last(c: char) -> bool { return c == '(' || c == ':'; }
@@ -437,14 +430,13 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
         inputs.push({mode: mode, ty: parse_ty(st, conv)});
     }
     st.pos += 1u; // eat the ']'
-    let (ret_style, ret_ty) = parse_ret_ty(st, conv);
+    let ret_ty = parse_ty(st, conv);
     return FnTyBase {
         meta: FnMeta {purity: purity,
                       proto: proto,
                       onceness: onceness,
                       bounds: bounds,
-                      region: region,
-                      ret_style: ret_style},
+                      region: region},
         sig: FnSig {inputs: inputs,
                     output: ret_ty}
     };
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index cf1a7db07a5..9612a28a401 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -388,10 +388,7 @@ fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) {
         enc_arg(w, cx, *arg);
     }
     w.write_char(']');
-    match ft.meta.ret_style {
-      noreturn => w.write_char('!'),
-      _ => enc_ty(w, cx, ft.sig.output)
-    }
+    enc_ty(w, cx, ft.sig.output);
 }
 
 fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 77a63b18778..635e2d18d6c 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -580,20 +580,22 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) {
         }
     }
 
-    let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
-        visit_expr: fn@(e: @ast::expr) {
-            match e.node {
-                ast::expr_binary(ref binop, @ref l, @ref r) => {
-                    if is_comparison(*binop)
-                       && !check_limits(cx, *binop, l, r) {
-                        cx.sess.span_lint(
-                            type_limits, e.id, it.id, e.span,
-                            ~"comparison is useless due to type limits");
-                    }
+    let visit_expr: @fn(@ast::expr) = |e| {
+        match e.node {
+            ast::expr_binary(ref binop, @ref l, @ref r) => {
+                if is_comparison(*binop)
+                    && !check_limits(cx, *binop, l, r) {
+                    cx.sess.span_lint(
+                        type_limits, e.id, it.id, e.span,
+                        ~"comparison is useless due to type limits");
                 }
-                _ => ()
             }
-        },
+            _ => ()
+        }
+    };
+
+    let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
+        visit_expr: visit_expr,
         .. *visit::default_simple_visitor()
     }));
     visit::visit_item(it, (), visit);
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index c3b4adeaf8b..317d0fbfd03 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -493,11 +493,10 @@ fn compare_scalar_types(cx: block, lhs: ValueRef, rhs: ValueRef,
 fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
                          nt: scalar_type, op: ast::binop) -> ValueRef {
     let _icx = cx.insn_ctxt("compare_scalar_values");
-    fn die_(cx: block) -> ! {
+    fn die(cx: block) -> ! {
         cx.tcx().sess.bug(~"compare_scalar_values: must be a\
           comparison operator");
     }
-    let die = fn@() -> ! { die_(cx) };
     match nt {
       nil_type => {
         // We don't need to do actual comparisons for nil.
@@ -506,7 +505,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
           ast::eq | ast::le | ast::ge => return C_bool(true),
           ast::ne | ast::lt | ast::gt => return C_bool(false),
           // refinements would be nice
-          _ => die()
+          _ => die(cx)
         }
       }
       floating_point => {
@@ -517,7 +516,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
           ast::le => lib::llvm::RealOLE,
           ast::gt => lib::llvm::RealOGT,
           ast::ge => lib::llvm::RealOGE,
-          _ => die()
+          _ => die(cx)
         };
         return FCmp(cx, cmp, lhs, rhs);
       }
@@ -529,7 +528,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
           ast::le => lib::llvm::IntSLE,
           ast::gt => lib::llvm::IntSGT,
           ast::ge => lib::llvm::IntSGE,
-          _ => die()
+          _ => die(cx)
         };
         return ICmp(cx, cmp, lhs, rhs);
       }
@@ -541,7 +540,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
           ast::le => lib::llvm::IntULE,
           ast::gt => lib::llvm::IntUGT,
           ast::ge => lib::llvm::IntUGE,
-          _ => die()
+          _ => die(cx)
         };
         return ICmp(cx, cmp, lhs, rhs);
       }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 9777d87513c..85aed8d5387 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -1022,8 +1022,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
                               proto: ast::ProtoBorrowed,
                               onceness: ast::Many,
                               region: ty::re_bound(ty::br_anon(0)),
-                              bounds: @~[],
-                              ret_style: ast::return_val},
+                              bounds: @~[]},
                 sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val),
                                        ty: star_u8}],
                             output: ty::mk_nil(bcx.tcx())}
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 4b5fdedb738..ccbced417e2 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -280,8 +280,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> {
                                         proto: fty.meta.proto,
                                         onceness: ast::Many,
                                         region: ty::re_static,
-                                        bounds: @~[],
-                                        ret_style: ast::return_val},
+                                        bounds: @~[]},
                           sig: FnSig {inputs: ~[],
                                       output: ty::mk_nil(tcx)}}))
         }
@@ -292,8 +291,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> {
                                         proto: ast::ProtoBox,
                                         onceness: ast::Many,
                                         region: ty::re_static,
-                                        bounds: @~[],
-                                        ret_style: ast::return_val},
+                                        bounds: @~[]},
                           sig: FnSig {inputs: ~[],
                                       output: ty::mk_nil(tcx)}}))
         }
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 239ed6b83ee..39ab5735dee 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -219,11 +219,7 @@ impl reflector {
               ast::extern_fn => 3u
             };
             let protoval = ast_proto_constant(fty.meta.proto);
-            let retval = match fty.meta.ret_style {
-              ast::noreturn => 0u,
-              ast::return_val => 1u
-            };
-            // XXX: Must we allocate here?
+            let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
             let extra = ~[self.c_uint(pureval),
                           self.c_uint(protoval),
                           self.c_uint(vec::len(fty.sig.inputs)),
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 1841d0b17e3..1435f0c66da 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -116,7 +116,7 @@ export ty_opaque_closure_ptr, mk_opaque_closure_ptr;
 export ty_opaque_box, mk_opaque_box;
 export ty_float, mk_float, mk_mach_float, type_is_fp;
 export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn;
-export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
+export ty_fn_proto, ty_fn_purity, ty_fn_ret, tys_in_fn_ty;
 export ty_int, mk_int, mk_mach_int, mk_char;
 export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
 export mk_f32, mk_f64;
@@ -219,7 +219,6 @@ export terr_regions_not_same, terr_regions_no_overlap;
 export terr_regions_insufficiently_polymorphic;
 export terr_regions_overly_polymorphic;
 export terr_proto_mismatch;
-export terr_ret_style_mismatch;
 export terr_fn, terr_trait;
 export purity_to_str;
 export onceness_to_str;
@@ -517,15 +516,13 @@ pure fn type_id(t: t) -> uint { get(t).id }
  * - `onceness` indicates whether the function can be called one time or many
  *   times.
  * - `region` is the region bound on the function's upvars (often &static).
- * - `bounds` is the parameter bounds on the function's upvars.
- * - `ret_style` indicates whether the function returns a value or fails. */
+ * - `bounds` is the parameter bounds on the function's upvars. */
 struct FnMeta {
     purity: ast::purity,
     proto: ast::Proto,
     onceness: ast::Onceness,
     region: Region,
-    bounds: @~[param_bound],
-    ret_style: ret_style
+    bounds: @~[param_bound]
 }
 
 /**
@@ -695,7 +692,6 @@ struct expected_found<T> {
 // Data structures used in type unification
 enum type_err {
     terr_mismatch,
-    terr_ret_style_mismatch(expected_found<ast::ret_style>),
     terr_purity_mismatch(expected_found<purity>),
     terr_onceness_mismatch(expected_found<Onceness>),
     terr_mutability,
@@ -2819,11 +2815,10 @@ impl arg : to_bytes::IterBytes {
 
 impl FnMeta : to_bytes::IterBytes {
     pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
-        to_bytes::iter_bytes_5(&self.purity,
+        to_bytes::iter_bytes_4(&self.purity,
                                &self.proto,
                                &self.region,
                                &self.bounds,
-                               &self.ret_style,
                                lsb0, f);
     }
 }
@@ -2969,13 +2964,6 @@ pure fn ty_fn_ret(fty: t) -> t {
     }
 }
 
-fn ty_fn_ret_style(fty: t) -> ast::ret_style {
-    match get(fty).sty {
-      ty_fn(ref f) => f.meta.ret_style,
-      _ => fail ~"ty_fn_ret_style() called on non-fn type"
-    }
-}
-
 fn is_fn_ty(fty: t) -> bool {
     match get(fty).sty {
       ty_fn(_) => true,
@@ -3435,17 +3423,6 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
 
     match *err {
         terr_mismatch => ~"types differ",
-        terr_ret_style_mismatch(values) => {
-            fn to_str(s: ast::ret_style) -> ~str {
-                match s {
-                    ast::noreturn => ~"non-returning",
-                    ast::return_val => ~"return-by-value"
-                }
-            }
-            fmt!("expected %s function, found %s function",
-                 to_str(values.expected),
-                 to_str(values.expected))
-        }
         terr_purity_mismatch(values) => {
             fmt!("expected %s fn but found %s fn",
                  purity_to_str(values.expected),
@@ -4406,8 +4383,7 @@ impl FnMeta : cmp::Eq {
     pure fn eq(&self, other: &FnMeta) -> bool {
         (*self).purity == (*other).purity &&
         (*self).proto == (*other).proto &&
-        (*self).bounds == (*other).bounds &&
-        (*self).ret_style == (*other).ret_style
+        (*self).bounds == (*other).bounds
     }
     pure fn ne(&self, other: &FnMeta) -> bool { !(*self).eq(other) }
 }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 635a83ba251..b290f6c1742 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -507,8 +507,7 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Durable>(
                           proto: ast_proto,
                           onceness: onceness,
                           region: bound_region,
-                          bounds: bounds,
-                          ret_style: decl.cf},
+                          bounds: bounds},
             sig: FnSig {inputs: input_tys,
                         output: output_ty}
         }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 1d8b0a74199..bd8b6934e0d 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1091,6 +1091,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
 
                   let supplied_arg_count = args.len();
 
+                  bot |= ty::type_is_bot(fn_ty.sig.output);
+
                   // Grab the argument types, supplying fresh type variables
                   // if the wrong number of arguments were supplied
                   let expected_arg_count = fn_ty.sig.inputs.len();
@@ -1218,7 +1220,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         // Pull the return type out of the type of the function.
         match structure_of(fcx, sp, fty) {
           ty::ty_fn(ref f) => {
-              bot |= (f.meta.ret_style == ast::noreturn);
               fcx.write_ty(call_expr_id, f.sig.output);
               return bot;
           }
@@ -3078,8 +3079,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
                           proto: ast::ProtoBorrowed,
                           onceness: ast::Once,
                           region: ty::re_bound(ty::br_anon(0)),
-                          bounds: @~[],
-                          ret_style: ast::return_val},
+                          bounds: @~[]},
             sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val),
                                    ty: ty::mk_imm_ptr(
                                        ccx.tcx,
@@ -3291,8 +3291,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
                       proto: ast::ProtoBare,
                       onceness: ast::Many,
                       region: ty::re_static,
-                      bounds: @~[],
-                      ret_style: ast::return_val},
+                      bounds: @~[]},
         sig: FnSig {inputs: inputs,
                     output: output}
     });
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 48c16a94212..e8d424b899f 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -161,8 +161,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
                                   proto: ast::ProtoBare,
                                   onceness: ast::Many,
                                   bounds: @~[],
-                                  region: ty::re_static,
-                                  ret_style: ast::return_val},
+                                  region: ty::re_static},
                     sig: FnSig {inputs: args,
                                 output: enum_ty}
                 }));
@@ -195,8 +194,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
                                   proto: ast::ProtoBare,
                                   onceness: ast::Many,
                                   bounds: @~[],
-                                  region: ty::re_static,
-                                  ret_style: ast::return_val},
+                                  region: ty::re_static},
                     sig: FnSig {inputs: struct_fields, output: enum_ty }}));
             }
             ast::enum_variant_kind(ref enum_definition) => {
@@ -698,8 +696,7 @@ fn convert_struct(ccx: @crate_ctxt,
                         proto: ast::ProtoBare,
                         onceness: ast::Many,
                         bounds: @~[],
-                        region: ty::re_static,
-                        ret_style: ast::return_val,
+                        region: ty::re_static
                     },
                     sig: FnSig {
                         inputs: do struct_def.fields.map |field| {
@@ -967,8 +964,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
                       onceness: ast::Many,
                       proto: ast::ProtoBare,
                       bounds: @~[],
-                      region: ty::re_static,
-                      ret_style: ast::return_val},
+                      region: ty::re_static},
         sig: FnSig {inputs: input_tys,
                     output: output_ty}
     });
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index e612a76b92d..514ae87800d 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -88,7 +88,6 @@ trait combine {
     fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
     fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>;
     fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto>;
-    fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
     fn purities(a: purity, b: purity) -> cres<purity>;
     fn oncenesses(a: Onceness, b: Onceness) -> cres<Onceness>;
     fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region>;
@@ -331,15 +330,13 @@ fn super_fn_metas<C:combine>(
 {
     let p = if_ok!(self.protos(a_f.proto, b_f.proto));
     let r = if_ok!(self.contraregions(a_f.region, b_f.region));
-    let rs = if_ok!(self.ret_styles(a_f.ret_style, b_f.ret_style));
     let purity = if_ok!(self.purities(a_f.purity, b_f.purity));
     let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness));
     Ok(FnMeta {purity: purity,
                proto: p,
                region: r,
                onceness: onceness,
-               bounds: a_f.bounds, // XXX: This is wrong!
-               ret_style: rs})
+               bounds: a_f.bounds}) // XXX: This is wrong!
 }
 
 fn super_fn_sigs<C:combine>(
diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs
index f4139c4cf49..1d27312c509 100644
--- a/src/librustc/middle/typeck/infer/glb.rs
+++ b/src/librustc/middle/typeck/infer/glb.rs
@@ -105,18 +105,6 @@ impl Glb: combine {
         }
     }
 
-    fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
-        match (r1, r2) {
-          (ast::return_val, ast::return_val) => {
-            Ok(ast::return_val)
-          }
-          (ast::noreturn, _) |
-          (_, ast::noreturn) => {
-            Ok(ast::noreturn)
-          }
-        }
-    }
-
     fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("%s.regions(%?, %?)",
                self.tag(),
diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs
index 53c9b263034..8a6cfd13d51 100644
--- a/src/librustc/middle/typeck/infer/lub.rs
+++ b/src/librustc/middle/typeck/infer/lub.rs
@@ -98,14 +98,6 @@ impl Lub: combine {
         }
     }
 
-    fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
-        match (r1, r2) {
-          (ast::return_val, _) |
-          (_, ast::return_val) => Ok(ast::return_val),
-          (ast::noreturn, ast::noreturn) => Ok(ast::noreturn)
-        }
-    }
-
     fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         return Glb(*self).regions(a, b);
     }
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index cc7733231ed..1b0c71dc890 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -96,12 +96,6 @@ impl Sub: combine {
         })
     }
 
-    fn ret_styles(a: ret_style, b: ret_style) -> cres<ret_style> {
-        self.lub().ret_styles(a, b).compare(b, || {
-            ty::terr_ret_style_mismatch(expected_found(&self, a, b))
-        })
-    }
-
     fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
         debug!("%s.tys(%s, %s)", self.tag(),
                a.to_str(self.infcx), b.to_str(self.infcx));
diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs
index c3d2c8e99f7..94fe6090c6b 100644
--- a/src/librustc/middle/typeck/infer/test.rs
+++ b/src/librustc/middle/typeck/infer/test.rs
@@ -181,8 +181,7 @@ impl Env {
                           proto: ast::ProtoBare,
                           onceness: ast::Many,
                           region: ty::re_static,
-                          bounds: @~[],
-                          ret_style: ast::return_val},
+                          bounds: @~[]},
             sig: FnSig {inputs: move inputs,
                         output: output_ty}
         })
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 12dd40356eb..c81ad60e083 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -259,7 +259,7 @@ fn expr_repr(cx: ctxt, expr: @ast::expr) -> ~str {
          pprust::expr_to_str(expr, cx.sess.intr()))
 }
 
-fn tys_to_str(cx: ctxt, ts: ~[t]) -> ~str {
+fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
     let tstrs = ts.map(|t| ty_to_str(cx, *t));
     fmt!("[%s]", str::connect(tstrs, ", "))
 }
@@ -291,9 +291,8 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
                  purity: ast::purity,
                  onceness: ast::Onceness,
                  ident: Option<ast::ident>,
-                 inputs: ~[arg],
-                 output: t,
-                 cf: ast::ret_style) -> ~str {
+                 inputs: &[arg],
+                 output: t) -> ~str {
         let mut s;
 
         s = match purity {
@@ -331,9 +330,10 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
         s += ~")";
         if ty::get(output).sty != ty_nil {
             s += ~" -> ";
-            match cf {
-              ast::noreturn => { s += ~"!"; }
-              ast::return_val => { s += ty_to_str(cx, output); }
+            if ty::type_is_bot(output) {
+                s += ~"!";
+            } else {
+                s += ty_to_str(cx, output);
             }
         }
         return s;
@@ -347,8 +347,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
             m.fty.meta.onceness,
             Some(m.ident),
             m.fty.sig.inputs,
-            m.fty.sig.output,
-            m.fty.meta.ret_style) + ~";";
+            m.fty.sig.output) + ~";";
     }
     fn field_to_str(cx: ctxt, f: field) -> ~str {
         return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt);
@@ -364,7 +363,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
     // pretty print the structural type representation:
     return match /*bad*/copy ty::get(typ).sty {
       ty_nil => ~"()",
-      ty_bot => ~"_|_",
+      ty_bot => ~"!",
       ty_bool => ~"bool",
       ty_int(ast::ty_i) => ~"int",
       ty_int(ast::ty_char) => ~"char",
@@ -396,9 +395,8 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
                   f.meta.purity,
                   f.meta.onceness,
                   None,
-                  /*bad*/copy f.sig.inputs,
-                  f.sig.output,
-                  f.meta.ret_style)
+                  f.sig.inputs,
+                  f.sig.output)
       }
       ty_infer(infer_ty) => infer_ty.to_str(),
       ty_err => ~"[type error]",
@@ -409,15 +407,12 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
       ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
         let path = ty::item_path(cx, did);
         let base = ast_map::path_to_str(path, cx.sess.intr());
-        parameterized(cx, base, (*substs).self_r, /*bad*/copy (*substs).tps)
+        parameterized(cx, base, substs.self_r, substs.tps)
       }
       ty_trait(did, ref substs, vs) => {
         let path = ty::item_path(cx, did);
         let base = ast_map::path_to_str(path, cx.sess.intr());
-        let result = parameterized(cx,
-                                   base,
-                                   substs.self_r,
-                                   /*bad*/copy substs.tps);
+        let result = parameterized(cx, base, substs.self_r, substs.tps);
         vstore_ty_to_str(cx, result, vs)
       }
       ty_evec(mt, vs) => {
@@ -433,9 +428,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
 }
 
 fn parameterized(cx: ctxt,
-                 base: ~str,
+                 base: &str,
                  self_r: Option<ty::Region>,
-                 tps: ~[ty::t]) -> ~str {
+                 tps: &[ty::t]) -> ~str {
 
     let r_str = match self_r {
       None => ~"",
diff --git a/src/test/compile-fail/bad-bang-ann-3.rs b/src/test/compile-fail/bad-bang-ann-3.rs
index 3f4d60a5ec9..9e73bbe1406 100644
--- a/src/test/compile-fail/bad-bang-ann-3.rs
+++ b/src/test/compile-fail/bad-bang-ann-3.rs
@@ -13,7 +13,7 @@
 
 fn bad_bang(i: uint) -> ! {
     return 7u;
-    //~^ ERROR expected `_|_` but found `uint`
+    //~^ ERROR expected `!` but found `uint`
 }
 
 fn main() { bad_bang(5u); }
diff --git a/src/test/compile-fail/bad-bang-ann.rs b/src/test/compile-fail/bad-bang-ann.rs
index da08692797f..4dbe5876a97 100644
--- a/src/test/compile-fail/bad-bang-ann.rs
+++ b/src/test/compile-fail/bad-bang-ann.rs
@@ -13,7 +13,7 @@
 
 fn bad_bang(i: uint) -> ! {
     if i < 0u { } else { fail; }
-    //~^ ERROR expected `_|_` but found `()`
+    //~^ ERROR expected `!` but found `()`
 }
 
 fn main() { bad_bang(5u); }
diff --git a/src/test/compile-fail/bang-tailexpr.rs b/src/test/compile-fail/bang-tailexpr.rs
index fa33e1f832b..af78e19e8c2 100644
--- a/src/test/compile-fail/bang-tailexpr.rs
+++ b/src/test/compile-fail/bang-tailexpr.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn f() -> ! {
-    3i //~ ERROR expected `_|_` but found `int`
+    3i //~ ERROR expected `!` but found `int`
 }
 fn main() { }
diff --git a/src/test/compile-fail/closure-that-fails.rs b/src/test/compile-fail/closure-that-fails.rs
new file mode 100644
index 00000000000..00bfa7a2233
--- /dev/null
+++ b/src/test/compile-fail/closure-that-fails.rs
@@ -0,0 +1,7 @@
+fn foo(f: fn() -> !) {}
+
+fn main() {
+    // Type inference didn't use to be able to handle this:
+    foo(|| fail);
+    foo(|| 22); //~ ERROR mismatched types
+}
diff --git a/src/test/compile-fail/issue-897-2.rs b/src/test/compile-fail/issue-897-2.rs
index 77de0b115cb..61afdab405d 100644
--- a/src/test/compile-fail/issue-897-2.rs
+++ b/src/test/compile-fail/issue-897-2.rs
@@ -10,7 +10,7 @@
 
 fn g() -> ! { fail; }
 fn f() -> ! {
-    return 42i; //~ ERROR expected `_|_` but found `int`
+    return 42i; //~ ERROR expected `!` but found `int`
     g(); //~ WARNING unreachable statement
 }
 fn main() { }
diff --git a/src/test/compile-fail/issue-897.rs b/src/test/compile-fail/issue-897.rs
index 3086bcc9b3f..1ed7034be77 100644
--- a/src/test/compile-fail/issue-897.rs
+++ b/src/test/compile-fail/issue-897.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn f() -> ! {
-    return 42i; //~ ERROR expected `_|_` but found `int`
+    return 42i; //~ ERROR expected `!` but found `int`
     fail; //~ WARNING unreachable statement
 }
 fn main() { }
diff --git a/src/test/compile-fail/loop-does-not-diverge.rs b/src/test/compile-fail/loop-does-not-diverge.rs
index 77b906ca9a2..0265bd6d24b 100644
--- a/src/test/compile-fail/loop-does-not-diverge.rs
+++ b/src/test/compile-fail/loop-does-not-diverge.rs
@@ -14,7 +14,7 @@ fn forever() -> ! {
   loop {
     break;
   }
-  return 42i; //~ ERROR expected `_|_` but found `int`
+  return 42i; //~ ERROR expected `!` but found `int`
 }
 
 fn main() {