improve error messages

This commit is contained in:
Niko Matsakis 2012-04-06 06:58:41 -07:00
parent ce8023b9ac
commit 2c56ba7e43
11 changed files with 105 additions and 45 deletions

View File

@ -493,7 +493,7 @@ impl unify_methods for infer_ctxt {
if b == r {
self.uok()
} else {
err(ty::terr_regions_differ(false, b, a))
err(ty::terr_regions_differ(b, a))
}
}
}
@ -521,21 +521,23 @@ impl unify_methods for infer_ctxt {
}
}
/* mk_subty passes the "smaller" type as the first argument
and the "bigger" type as the second -- so the first arg
is the actual type, and the second is the expected type */
fn flds(a: ty::field, e: ty::field) -> ures {
if e.ident != a.ident {
ret self.uerr(ty::terr_record_fields(e.ident, a.ident));
fn flds(a: ty::field, b: ty::field) -> ures {
if b.ident != a.ident {
// Note: the error object expects the "expected" field to
// come first, which is generally the supertype (b).
ret self.uerr(ty::terr_record_fields(b.ident, a.ident));
}
self.mts(a.mt, b.mt).chain_err {|err|
self.uerr(ty::terr_in_field(@err, a.ident))
}
self.mts(a.mt, e.mt)
}
fn tps(as: [ty::t], bs: [ty::t]) -> ures {
if check vec::same_length(as, bs) {
iter2(as, bs) {|a, b| self.tys(a, b) }
} else {
self.uerr(ty::terr_ty_param_size(as.len(), bs.len()))
self.uerr(ty::terr_ty_param_size(bs.len(), as.len()))
}
}
@ -544,7 +546,7 @@ impl unify_methods for infer_ctxt {
(_, ast::proto_any) { self.uok() }
(ast::proto_bare, _) { self.uok() }
(_, _) if a == b { self.uok() }
_ { self.uerr(ty::terr_proto_mismatch(a, b)) }
_ { self.uerr(ty::terr_proto_mismatch(b, a)) }
}
}
@ -558,7 +560,7 @@ impl unify_methods for infer_ctxt {
this check is necessary to ensure that the
annotation in an object method matches the
declared object type */
self.uerr(ty::terr_ret_style_mismatch(a_ret_style, b_ret_style))
self.uerr(ty::terr_ret_style_mismatch(b_ret_style, a_ret_style))
} else {
self.uok()
}
@ -672,7 +674,7 @@ impl unify_methods for infer_ctxt {
self.constrs(a, b)
}
} else {
self.uerr(ty::terr_constr_len(as.len(), bs.len()))
self.uerr(ty::terr_constr_len(bs.len(), as.len()))
}
}
@ -713,7 +715,7 @@ impl unify_methods for infer_ctxt {
if ty::mach_sty(cfg, a) == ty::mach_sty(cfg, b) {
self.uok()
} else {
self.uerr(ty::terr_mismatch)
self.uerr(ty::terr_sorts(b, a))
}
}
@ -757,8 +759,8 @@ impl unify_methods for infer_ctxt {
self.flds(a, b)
}
} else {
ret self.uerr(ty::terr_record_size(a_fields.len(),
b_fields.len()));
ret self.uerr(ty::terr_record_size(b_fields.len(),
a_fields.len()));
}
}
@ -766,7 +768,7 @@ impl unify_methods for infer_ctxt {
if check vec::same_length(a_tys, b_tys) {
iter2(a_tys, b_tys) {|a,b| self.tys(a,b) }
} else {
self.uerr(ty::terr_tuple_size(a_tys.len(), b_tys.len()))
self.uerr(ty::terr_tuple_size(b_tys.len(), a_tys.len()))
}
}
@ -780,7 +782,7 @@ impl unify_methods for infer_ctxt {
}
}
_ { self.uerr(ty::terr_mismatch) }
_ { self.uerr(ty::terr_sorts(b, a)) }
}
}
}
@ -1066,7 +1068,7 @@ fn c_tuptys<C:combine>(self: C, as: [ty::t], bs: [ty::t])
if check vec::same_length(as, bs) {
map2(as, bs) {|a, b| self.c_tys(a, b) }
} else {
err(ty::terr_tuple_size(as.len(), bs.len()))
err(ty::terr_tuple_size(bs.len(), as.len()))
}
}
@ -1077,7 +1079,7 @@ fn c_tps<C:combine>(self: C, _did: ast::def_id, as: [ty::t], bs: [ty::t])
if check vec::same_length(as, bs) {
map2(as, bs) {|a,b| self.c_tys(a, b) }
} else {
err(ty::terr_ty_param_size(as.len(), bs.len()))
err(ty::terr_ty_param_size(bs.len(), as.len()))
}
}
@ -1087,17 +1089,17 @@ fn c_fieldvecs<C:combine>(self: C, as: [ty::field], bs: [ty::field])
if check vec::same_length(as, bs) {
map2(as, bs) {|a,b| c_flds(self, a, b) }
} else {
err(ty::terr_record_size(as.len(), bs.len()))
err(ty::terr_record_size(bs.len(), as.len()))
}
}
fn c_flds<C:combine>(self: C, e: ty::field, a: ty::field) -> cres<ty::field> {
if e.ident == a.ident {
self.c_mts(e.mt, a.mt).chain {|mt|
ok({ident: e.ident, mt: mt})
fn c_flds<C:combine>(self: C, a: ty::field, b: ty::field) -> cres<ty::field> {
if a.ident == b.ident {
self.c_mts(a.mt, b.mt).chain {|mt|
ok({ident: a.ident, mt: mt})
}
} else {
err(ty::terr_record_fields(e.ident, a.ident))
err(ty::terr_record_fields(b.ident, a.ident))
}
}
@ -1196,7 +1198,7 @@ fn c_tys<C:combine>(
if ty::mach_sty(cfg, a) == ty::mach_sty(cfg, b) {
ok(a)
} else {
err(ty::terr_mismatch)
err(ty::terr_sorts(b, a))
}
}
@ -1293,7 +1295,7 @@ fn c_tys<C:combine>(
}
}
_ { err(ty::terr_mismatch) }
_ { err(ty::terr_sorts(b, a)) }
}
}
}
@ -1350,14 +1352,14 @@ fn c_regions<C:combine>(
#debug["... no, %s != %s.",
a.to_str(self.infcx()),
b.to_str(self.infcx())];
err(ty::terr_regions_differ(false, b, a))
err(ty::terr_regions_differ(b, a))
}
}
(ty::re_default, _) |
(_, ty::re_default) {
// actually a compiler bug, I think.
err(ty::terr_regions_differ(false, b, a))
err(ty::terr_regions_differ(b, a))
}
}
}
@ -1480,7 +1482,7 @@ impl of combine for lub {
let rm = self.infcx().tcx.region_map;
alt region::nearest_common_ancestor(rm, a_id, b_id) {
some(r_id) { ok(ty::re_scope(r_id)) }
_ { err(ty::terr_regions_differ(false, b, a)) }
_ { err(ty::terr_regions_differ(b, a)) }
}
}
}
@ -1623,7 +1625,7 @@ impl of combine for glb {
alt region::nearest_common_ancestor(rm, a_id, b_id) {
some(r_id) if a_id == r_id { ok(b) }
some(r_id) if b_id == r_id { ok(a) }
_ { err(ty::terr_regions_differ(false, b, a)) }
_ { err(ty::terr_regions_differ(b, a)) }
}
}
}

View File

@ -341,7 +341,9 @@ enum type_err {
terr_mode_mismatch(mode, mode),
terr_constr_len(uint, uint),
terr_constr_mismatch(@type_constr, @type_constr),
terr_regions_differ(bool /* variance */, region, region),
terr_regions_differ(region, region),
terr_in_field(@type_err, str),
terr_sorts(t, t)
}
enum param_bound {
@ -1837,6 +1839,33 @@ fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
}
}
fn ty_sort_str(cx: ctxt, t: t) -> str {
alt get(t).struct {
ty_nil | ty_bot | ty_bool | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_str | ty_type | ty_opaque_box |
ty_opaque_closure_ptr(_) {
ty_to_str(cx, t)
}
ty_enum(_, _) { "enum" }
ty_box(_) { "@-ptr" }
ty_uniq(_) { "~-ptr" }
ty_vec(_) { "vector" }
ty_ptr(_) { "*-ptr" }
ty_rptr(_, _) { "&-ptr" }
ty_rec(_) { "record" }
ty_fn(_) { "fn" }
ty_iface(_, _) { "iface" }
ty_class(_, _) { "class" }
ty_res(_, _, _) { "resource" }
ty_tup(_) { "tuple" }
ty_var(_) { "variable" }
ty_param(_, _) { "type parameter" }
ty_self(_) { "self" }
ty_constr(t, _) { ty_sort_str(cx, t) }
}
}
fn type_err_to_str(cx: ctxt, err: type_err) -> str {
alt err {
terr_mismatch { ret "types differ"; }
@ -1876,8 +1905,8 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> str {
}
terr_record_mutability { ret "record elements differ in mutability"; }
terr_record_fields(e_fld, a_fld) {
ret "expected a record with field '" + e_fld +
"' but found one with field '" + a_fld + "'";
ret "expected a record with field `" + e_fld +
"` but found one with field `" + a_fld + "`";
}
terr_arg_count { ret "incorrect number of function parameters"; }
terr_mode_mismatch(e_mode, a_mode) {
@ -1894,16 +1923,18 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> str {
" but found one with constraint " +
ty_constr_to_str(a_constr);
}
terr_regions_differ(true, region_a, region_b) {
ret #fmt("reference lifetime %s does not match reference lifetime %s",
region_to_str(cx, region_a), region_to_str(cx, region_b));
}
terr_regions_differ(false, subregion, superregion) {
terr_regions_differ(subregion, superregion) {
ret #fmt("references with lifetime %s do not outlive references with \
lifetime %s",
region_to_str(cx, subregion),
region_to_str(cx, superregion));
}
terr_in_field(err, fname) {
ret #fmt("in field `%s`, %s", fname, type_err_to_str(cx, *err));
}
terr_sorts(exp, act) {
ret #fmt("%s vs %s", ty_sort_str(cx, exp), ty_sort_str(cx, act));
}
}
}

View File

@ -3,7 +3,7 @@
fn bad_bang(i: uint) -> ! {
ret 7u;
//!^ ERROR expected `_|_` but found `uint` (types differ)
//!^ ERROR expected `_|_` but found `uint`
}
fn main() { bad_bang(5u); }

View File

@ -3,7 +3,7 @@
fn bad_bang(i: uint) -> ! {
if i < 0u { } else { fail; }
//!^ ERROR expected `_|_` but found `()` (types differ)
//!^ ERROR expected `_|_` but found `()`
}
fn main() { bad_bang(5u); }

View File

@ -1,4 +1,4 @@
fn f() -> ! {
3 //! ERROR expected `_|_` but found `int` (types differ)
3 //! ERROR expected `_|_` but found `int`
}
fn main() { }

View File

@ -1,6 +1,6 @@
fn g() -> ! { fail; }
fn f() -> ! {
ret 42; //! ERROR expected `_|_` but found `int` (types differ)
ret 42; //! ERROR expected `_|_` but found `int`
g(); //! WARNING unreachable statement
}
fn main() { }

View File

@ -1,5 +1,5 @@
fn f() -> ! {
ret 42; //! ERROR expected `_|_` but found `int` (types differ)
ret 42; //! ERROR expected `_|_` but found `int`
fail; //! WARNING unreachable statement
}
fn main() { }

View File

@ -4,7 +4,7 @@ fn forever() -> ! {
loop {
break;
}
ret 42; //! ERROR expected `_|_` but found `int` (types differ)
ret 42; //! ERROR expected `_|_` but found `int`
}
fn main() {

View File

@ -0,0 +1,9 @@
type foo = {a: int};
type bar = {b: int};
fn want_foo(f: foo) {}
fn have_bar(b: bar) {
want_foo(b); //! ERROR expected a record with field `a`
}
fn main() {}

View File

@ -0,0 +1,9 @@
type foo = {a: int, b: int};
type bar = {a: int, b: uint};
fn want_foo(f: foo) {}
fn have_bar(b: bar) {
want_foo(b); //! ERROR (in field `b`, int vs uint)
}
fn main() {}

View File

@ -0,0 +1,9 @@
type foo = {a: int, b: int};
type bar = @foo;
fn want_foo(f: foo) {}
fn have_bar(b: bar) {
want_foo(b); //! ERROR (record vs @-ptr)
}
fn main() {}