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:
parent
205cefdc6e
commit
8ab075ee45
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user