Remove ret_style and instead check whether fn return type is bot
cc #3681
This commit is contained in:
parent
80435ad429
commit
9f7dc1cb33
24 changed files with 70 additions and 145 deletions
|
|
@ -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}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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]) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())}
|
||||
|
|
|
|||
|
|
@ -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)}}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>(
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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 => ~"",
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
7
src/test/compile-fail/closure-that-fails.rs
Normal file
7
src/test/compile-fail/closure-that-fails.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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() { }
|
||||
|
|
|
|||
|
|
@ -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() { }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fn forever() -> ! {
|
|||
loop {
|
||||
break;
|
||||
}
|
||||
return 42i; //~ ERROR expected `_|_` but found `int`
|
||||
return 42i; //~ ERROR expected `!` but found `int`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue