diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2012-01-27 18:58:52 +0100 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2012-01-27 18:58:52 +0100 |
| commit | e48bf6f3f4d1ca07f0c2820c6cfaad275bc106ac (patch) | |
| tree | 7a2026c20a220710ad111dddae3e14ca6448c853 /src/comp | |
| parent | 362625008ab9e3479f7e34212e1887a3ad6d93b8 (diff) | |
| download | rust-e48bf6f3f4d1ca07f0c2820c6cfaad275bc106ac.tar.gz rust-e48bf6f3f4d1ca07f0c2820c6cfaad275bc106ac.zip | |
Make occurs check in ty::fixup_vars more reliable
It wouldn't detect cycles that went through several type vars before. Closes #1464
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/middle/ty.rs | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 944614ad03e..502510063df 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -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); } |
