提交 ef833d41 编写于 作者: T Tim Chevalier

Introduce a T_err type for type errors

This allows more errors to be non-fatal, as per #1871.

I only went through and started changing span_fatal to span_err in
check.rs. There are probably more errors that could be made
non-fatal. So if you see derived type errors appearing from now on,
file a bug!

r=graydon

Closes #1871
上级 77ef4e71
......@@ -318,6 +318,7 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) {
debug!("~~~~ %s", ~"]");
w.write_char(']');
}
ty::ty_err => fail ~"Shouldn't encode error type"
}
}
......
......@@ -266,6 +266,7 @@ fn visit_ty(t: ty::t) {
// Miscallaneous extra types
ty::ty_trait(_, _, _) => self.leaf(~"trait"),
ty::ty_infer(_) => self.leaf(~"infer"),
ty::ty_err => self.leaf(~"err"),
ty::ty_param(p) => self.visit(~"param", ~[self.c_uint(p.idx)]),
ty::ty_self => self.leaf(~"self"),
ty::ty_type => self.leaf(~"type"),
......
......@@ -179,6 +179,7 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"),
ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"),
ty::ty_err(*) => cx.tcx.sess.bug(~"type_of with ty_err")
};
cx.lltypes.insert(t, llty);
......
......@@ -57,7 +57,7 @@
export lookup_public_fields;
export method;
export method_idx;
export mk_class;
export mk_class, mk_err;
export mk_ctxt;
export mk_with_id, type_def_id;
export mt;
......@@ -87,6 +87,7 @@
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;
export ty_err;
export ty_estr, mk_estr, type_is_str;
export ty_evec, mk_evec, type_is_vec;
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
......@@ -127,7 +128,7 @@
export meta_kind, kind_lteq, type_kind;
export operators;
export type_err, terr_vstore_kind;
export terr_onceness_mismatch;
export terr_mismatch, terr_onceness_mismatch;
export type_err_to_str, note_and_explain_type_err;
export expected_found;
export type_needs_drop;
......@@ -673,6 +674,9 @@ enum sty {
ty_self, // special, implicit `self` type parameter
ty_infer(InferTy), // soething used only during inference/typeck
ty_err, // Also only used during inference/typeck, to represent
// the type of an erroneous expression (helps cut down
// on non-useful type error messages)
// "Fake" types, used for trans purposes
ty_type, // type_desc*
......@@ -1062,7 +1066,7 @@ fn sflags(substs: &substs) -> uint {
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_opaque_box => (),
ty_opaque_box | ty_err => (),
ty_param(_) => flags |= has_params as uint,
ty_infer(_) => flags |= needs_infer as uint,
ty_self => flags |= has_self as uint,
......@@ -1094,6 +1098,8 @@ fn sflags(substs: &substs) -> uint {
fn mk_nil(cx: ctxt) -> t { mk_t(cx, ty_nil) }
fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) }
fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) }
fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) }
......@@ -1301,7 +1307,7 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_box | ty_self |
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) => {
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
}
ty_box(tm) | ty_evec(tm, _) | ty_unboxed_vec(tm) |
ty_ptr(tm) | ty_rptr(_, tm) => {
......@@ -1386,7 +1392,7 @@ fn fold_substs(substs: &substs, fldop: fn(t) -> t) -> substs {
ty_class(did, fold_substs(substs, fldop))
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
*sty
}
......@@ -1794,7 +1800,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool {
ty_trait(_, _, vstore_fixed(_)) |
ty_trait(_, _, vstore_slice(_)) => false,
ty_param(*) | ty_infer(*) => true,
ty_param(*) | ty_infer(*) | ty_err => true,
ty_evec(mt, vstore_fixed(_)) => type_needs_drop(cx, mt.ty),
ty_unboxed_vec(mt) => type_needs_drop(cx, mt.ty),
......@@ -2270,7 +2276,7 @@ fn type_kind(cx: ctxt, ty: t) -> Kind {
cx.sess.bug(~"Asked to compute kind of a type variable");
}
ty_type | ty_opaque_closure_ptr(_)
| ty_opaque_box | ty_unboxed_vec(_) => {
| ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
cx.sess.bug(~"Asked to compute kind of fictitious type");
}
};
......@@ -2341,7 +2347,7 @@ fn type_size(cx: ctxt, ty: t) -> uint {
cx.sess.bug(~"Asked to compute kind of a type variable");
}
ty_type | ty_opaque_closure_ptr(_)
| ty_opaque_box | ty_unboxed_vec(_) => {
| ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
cx.sess.bug(~"Asked to compute kind of fictitious type");
}
}
......@@ -2384,6 +2390,7 @@ fn subtypes_require(cx: ctxt, seen: @mut ~[def_id],
ty_estr(_) |
ty_fn(_) |
ty_infer(_) |
ty_err |
ty_param(_) |
ty_self |
ty_type |
......@@ -2589,7 +2596,7 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
result = false;
}
ty_infer(*) | ty_self(*) => {
ty_infer(*) | ty_self(*) | ty_err => {
cx.sess.bug(~"non concrete type in type_is_pod");
}
}
......@@ -2862,6 +2869,8 @@ impl sty : to_bytes::IterBytes {
ty_rptr(ref r, ref mt) =>
to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
ty_err => 25u8.iter_bytes(lsb0, f)
}
}
}
......@@ -3357,7 +3366,8 @@ fn ty_sort_str(cx: ctxt, t: t) -> ~str {
ty_infer(IntVar(_)) => ~"integral variable",
ty_infer(FloatVar(_)) => ~"floating-point variable",
ty_param(_) => ~"type parameter",
ty_self => ~"self"
ty_self => ~"self",
ty_err => ~"type error"
}
}
......@@ -4787,6 +4797,12 @@ impl sty : cmp::Eq {
_ => false
}
}
ty_err => {
match (*other) {
ty_err => true,
_ => false
}
}
ty_param(e0a) => {
match (*other) {
ty_param(e0b) => e0a == e0b,
......@@ -4944,6 +4960,12 @@ impl sty : cmp::Eq {
_ => false
}
}
ty_err => {
match (*other) {
ty_err => true,
_ => false
}
}
ty_param(e0a) => {
match (*other) {
ty_param(e0b) => e0a == e0b,
......
此差异已折叠。
......@@ -697,6 +697,8 @@ fn search_for_autoptrd_method(
|m,r| ty::mk_rptr(tcx, r, {ty:self_ty, mutbl:m}))
}
ty_err => None,
ty_opaque_closure_ptr(_) | ty_unboxed_vec(_) |
ty_opaque_box | ty_type | ty_infer(TyVar(_)) => {
self.bug(fmt!("Unexpected type: %s",
......
......@@ -476,13 +476,7 @@ fn demand_suptype(vcx: &VtableContext, sp: span, e: ty::t, a: ty::t) {
match infer::mk_subty(vcx.infcx, false, sp, a, e) {
result::Ok(()) => {} // Ok.
result::Err(ref err) => {
vcx.tcx().sess.span_err(
sp,
fmt!("mismatched types: expected `%s` but found `%s` (%s)",
vcx.infcx.ty_to_str(e),
vcx.infcx.ty_to_str(a),
ty::type_err_to_str(vcx.tcx(), err)));
ty::note_and_explain_type_err(vcx.tcx(), err);
vcx.infcx.report_mismatched_types(sp, e, a, err);
}
}
}
......
......@@ -13,7 +13,7 @@
use middle::ty::{lookup_item_type, subst, t, ty_bot, ty_box, ty_class};
use middle::ty::{ty_bool, ty_enum, ty_int, ty_nil, ty_ptr, ty_rptr, ty_uint};
use middle::ty::{ty_float, ty_estr, ty_evec, ty_rec, ty_uniq};
use middle::ty::{ty_fn, ty_trait, ty_tup, ty_infer};
use middle::ty::{ty_err, ty_fn, ty_trait, ty_tup, ty_infer};
use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box};
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_is_ty_var};
use middle::typeck::infer::{infer_ctxt, can_mk_subty};
......@@ -76,7 +76,7 @@ fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t)
ty_estr(*) | ty_evec(*) | ty_rec(*) |
ty_fn(*) | ty_tup(*) | ty_infer(*) |
ty_param(*) | ty_self | ty_type | ty_opaque_box |
ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) => {
ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err => {
debug!("(getting base type) no base type; found %?",
get(original_type).sty);
None
......
......@@ -684,5 +684,43 @@ fn resolve_type_vars_if_possible(typ: ty::t) -> ty::t {
result::Err(_) => typ
}
}
fn type_error_message(sp: span, mk_msg: fn(~str) -> ~str,
actual_ty: ty::t, err: Option<&ty::type_err>) {
let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
// Don't report an error if actual type is ty_err.
match ty::get(actual_ty).sty {
ty::ty_err => return,
_ => ()
}
let error_str = err.map_default(~"", |t_err|
fmt!(" (%s)",
ty::type_err_to_str(self.tcx, *t_err)));
self.tcx.sess.span_err(sp,
fmt!("%s%s", mk_msg(self.ty_to_str(actual_ty)),
error_str));
err.iter(|err|
ty::note_and_explain_type_err(self.tcx, *err));
}
fn report_mismatched_types(sp: span, e: ty::t, a: ty::t,
err: &ty::type_err) {
// Don't report an error if expected is ty_err
let resolved_expected =
self.resolve_type_vars_if_possible(e);
let mk_msg = match ty::get(resolved_expected).sty {
ty::ty_err => return,
_ => {
// if I leave out : ~str, it infers &str and complains
|actual: ~str| {
fmt!("mismatched types: expected `%s` but found `%s`",
self.ty_to_str(resolved_expected), actual)
}
}
};
self.type_error_message(sp, mk_msg, a, Some(err));
}
}
......@@ -9,7 +9,7 @@
use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region};
use middle::ty::{ReSkolemized, ReVar};
use middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_enum};
use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int};
use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int};
use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
use middle::ty::{ty_ptr, ty_rec, ty_rptr, ty_self, ty_tup};
use middle::ty::{ty_type, ty_uniq, ty_uint, ty_infer};
......@@ -390,6 +390,7 @@ fn field_to_str(cx: ctxt, f: field) -> ~str {
f.meta.ret_style)
}
ty_infer(infer_ty) => infer_ty.to_str(),
ty_err => ~"[type error]",
ty_param({idx: id, _}) => {
~"'" + str::from_bytes(~[('a' as u8) + (id as u8)])
}
......
// error-pattern: cast from nil: () as u32
// error-pattern: cast from nil: `()` as `u32`
fn main() { let u = (assert true) as u32; }
\ No newline at end of file
// error-pattern: cast to nil: u32 as ()
// error-pattern: cast to nil: `u32` as `()`
fn main() { let u = 0u32 as (); }
\ No newline at end of file
// error-pattern:expected function or foreign function but found *u8
// error-pattern:expected function or foreign function but found `*u8`
extern fn f() {
}
......
// xfail-test
// Tests that we don't generate a spurious error about f.honk's type
// being undeterminable
fn main() {
let f = 42;
let _g = if f < 5 {
f.honk();
f.honk() //~ ERROR attempted access of field `honk`
}
else {
12
()
};
}
......@@ -11,5 +11,5 @@ fn bind<B>(f: fn(A) -> ~[B]) {
}
}
fn main() {
["hi"].bind({|x| [x] });
["hi"].bind({|x| [x] }); //~ ERROR attempted access of field `bind`
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册