Clean up occurs check code and give non-breaking loop {..}s _|_ type

The latter change is so that code dominated by a loop{ } without a
break gets considered unreachable.

The former change is just cosmetic (occurs_check_fails was a predicate
when it should be a unit-typed function that can fail).
This commit is contained in:
Tim Chevalier 2012-03-10 20:35:41 -08:00
parent 205cefdc6e
commit 8ab075ee45
2 changed files with 11 additions and 19 deletions

View File

@ -125,7 +125,7 @@
export unify;
export variant_info;
export walk_ty;
export occurs_check_fails;
export occurs_check;
export closure_kind;
export ck_block;
export ck_box;
@ -1088,7 +1088,7 @@ fn vars_in_type(cx: ctxt, ty: t) -> [int] {
fn type_autoderef(cx: ctxt, t: t) -> t {
let t1 = t;
while true {
loop {
alt get(t1).struct {
ty_box(mt) | ty_uniq(mt) { t1 = mt.ty; }
ty_res(_, inner, tps) {
@ -1427,28 +1427,22 @@ fn method_lteq(a: method, b: method) -> bool {
ret std::sort::merge_sort(bind method_lteq(_, _), meths);
}
fn occurs_check_fails(tcx: ctxt, sp: option<span>, vid: int, rt: t) ->
bool {
fn occurs_check(tcx: ctxt, sp: span, vid: int, rt: t) {
// Fast path
if !type_has_vars(rt) { ret false; }
if !type_has_vars(rt) { ret; }
// Occurs check!
if vec::contains(vars_in_type(tcx, rt), vid) {
alt sp {
some(s) {
// Maybe this should be span_err -- however, there's an
// assertion later on that the type doesn't contain
// variables, so in this case we have to be sure to die.
tcx.sess.span_fatal
(s, "type inference failed because I \
(sp, "type inference failed because I \
could not find a type\n that's both of the form "
+ ty_to_str(tcx, mk_var(tcx, vid)) +
" and of the form " + ty_to_str(tcx, rt) +
" - such a type would have to be infinitely large.");
}
_ { ret true; }
}
} else { ret false; }
}
}
// Maintains a little union-set tree for inferred modes. `canon()` returns

View File

@ -1005,15 +1005,13 @@ fn unify(fcx: @fn_ctxt, expected: ty::t, actual: ty::t) ->
// instead of ty::struct.
fn do_autoderef(fcx: @fn_ctxt, sp: span, t: ty::t) -> ty::t {
let t1 = t;
while true {
loop {
alt structure_of(fcx, sp, t1) {
ty::ty_box(inner) | ty::ty_uniq(inner) {
alt ty::get(t1).struct {
ty::ty_var(v1) {
if ty::occurs_check_fails(fcx.ccx.tcx, some(sp), v1,
ty::mk_box(fcx.ccx.tcx, inner)) {
break;
}
ty::occurs_check(fcx.ccx.tcx, sp, v1,
ty::mk_box(fcx.ccx.tcx, inner));
}
_ { }
}
@ -1033,8 +1031,7 @@ fn do_autoderef(fcx: @fn_ctxt, sp: span, t: ty::t) -> ty::t {
}
_ { ret t1; }
}
}
core::unreachable();
};
}
fn resolve_type_vars_if_possible(fcx: @fn_ctxt, typ: ty::t) -> ty::t {
@ -2326,6 +2323,7 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
ast::expr_loop(body) {
check_block_no_value(fcx, body);
write_ty(tcx, id, ty::mk_nil(tcx));
bot = !may_break(body);
}
ast::expr_alt(expr, arms, _) {
bot = check_expr(fcx, expr);