Make occurs check in ty::fixup_vars more reliable

It wouldn't detect cycles that went through several type vars before.

Closes #1464
This commit is contained in:
Marijn Haverbeke 2012-01-27 18:58:52 +01:00
parent 362625008a
commit e48bf6f3f4
3 changed files with 21 additions and 13 deletions

View file

@ -2421,7 +2421,8 @@ mod unify {
fn fixup_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
typ: t) -> fixup_result {
fn subst_vars(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
unresolved: @mutable option::t<int>, vid: int) -> t {
unresolved: @mutable option::t<int>,
vars_seen: std::list::list<int>, vid: int) -> t {
// Should really return a fixup_result instead of a t, but fold_ty
// doesn't allow returning anything but a t.
if vid as uint >= ufind::set_count(vb.sets) {
@ -2432,21 +2433,28 @@ mod unify {
alt smallintmap::find::<t>(vb.types, root_id) {
none { *unresolved = some(vid); ret ty::mk_var(tcx, vid); }
some(rt) {
if occurs_check_fails(tcx, sp, vid, rt) {
// Return the type unchanged, so we can error out
// downstream
ret rt;
let give_up = false;
std::list::iter(vars_seen) {|v|
if v == vid {
give_up = true;
option::may(sp) {|sp|
tcx.sess.span_fatal(
sp, "can not instantiate infinite type");
}
}
}
ret fold_ty(tcx,
fm_var(bind subst_vars(tcx, sp, vb, unresolved,
_)), rt);
// Return the type unchanged, so we can error out
// downstream
if give_up { ret rt; }
ret fold_ty(tcx, fm_var(bind subst_vars(
tcx, sp, vb, unresolved, std::list::cons(vid, @vars_seen),
_)), rt);
}
}
}
let unresolved = @mutable none::<int>;
let rty =
fold_ty(tcx, fm_var(bind subst_vars(tcx, sp, vb, unresolved, _)),
typ);
let rty = fold_ty(tcx, fm_var(bind subst_vars(
tcx, sp, vb, unresolved, std::list::nil, _)), typ);
let ur = *unresolved;
alt ur {
none { ret fix_ok(rty); }

View file

@ -128,7 +128,7 @@ Function: tail
Returns all but the first element of a list
*/
pure fn tail<T: copy>(ls: list<T>) : is_not_empty(ls) -> list<T> {
pure fn tail<T: copy>(ls: list<T>) -> list<T> {
alt ls {
cons(_, tl) { ret *tl; }
nil { fail "list empty" }

View file

@ -1,2 +1,2 @@
// error-pattern: Type inference failed because I could not find
// error-pattern: can not instantiate infinite type
fn main() { let f; f = @f; }