repair LUB/GLB of free/scope regions, and enable test
This commit is contained in:
parent
58f8cb343d
commit
6b549f9f14
@ -1373,23 +1373,28 @@ impl of combine for lub {
|
||||
ok(ty::re_static) // nothing lives longer than static
|
||||
}
|
||||
|
||||
(ty::re_var(a_id), ty::re_var(b_id)) {
|
||||
lattice_vars(self, self.infcx().rb,
|
||||
a, a_id, b_id,
|
||||
{|x, y| self.regions(x, y) })
|
||||
(ty::re_var(_), _) | (_, ty::re_var(_)) {
|
||||
lattice_rvars(self, a, b)
|
||||
}
|
||||
|
||||
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
|
||||
lattice_var_t(self, self.infcx().rb,
|
||||
v_id, r,
|
||||
{|x, y| self.regions(x, y) })
|
||||
}
|
||||
|
||||
(f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
|
||||
(ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
|
||||
// for LUB, the scope is within the function and the free
|
||||
// region is always a parameter to the method.
|
||||
ok(f) // NDM--not so for nested functions
|
||||
(f @ ty::re_free(f_id, _), ty::re_scope(s_id)) |
|
||||
(ty::re_scope(s_id), f @ ty::re_free(f_id, _)) {
|
||||
// For LUB, generally the scope is within the fn and
|
||||
// the free region is a parameter to the fn. In that case,
|
||||
// the free region will always live as long as the fn,
|
||||
// which is longer than the scope.
|
||||
//
|
||||
// However, with nested fns, it can happen that the
|
||||
// scope surrounds the fn itself. In that case, we do
|
||||
// not know which will live longer---it depends on the
|
||||
// value provided for the free region in any given
|
||||
// call. And so we must just back off to re_static as
|
||||
// the LUB.
|
||||
let rm = self.infcx().tcx.region_map;
|
||||
alt region::nearest_common_ancestor(rm, f_id, s_id) {
|
||||
some(r_id) if r_id == f_id { ok(f) }
|
||||
_ { ok(ty::re_static) }
|
||||
}
|
||||
}
|
||||
|
||||
(ty::re_scope(a_id), ty::re_scope(b_id)) {
|
||||
@ -1399,7 +1404,7 @@ impl of combine for lub {
|
||||
let rm = self.infcx().tcx.region_map;
|
||||
alt region::nearest_common_ancestor(rm, a_id, b_id) {
|
||||
some(r_id) { ok(ty::re_scope(r_id)) }
|
||||
_ { err(ty::terr_regions_differ(b, a)) }
|
||||
_ { ok(ty::re_static) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1414,7 +1419,7 @@ impl of combine for lub {
|
||||
if a == b {
|
||||
ok(a)
|
||||
} else {
|
||||
err(ty::terr_regions_differ(b, a))
|
||||
ok(ty::re_static)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1551,24 +1556,26 @@ impl of combine for glb {
|
||||
ok(r)
|
||||
}
|
||||
|
||||
(ty::re_var(a_id), ty::re_var(b_id)) {
|
||||
lattice_vars(self, self.infcx().rb,
|
||||
a, a_id, b_id,
|
||||
{|x, y| self.regions(x, y) })
|
||||
(ty::re_var(_), _) | (_, ty::re_var(_)) {
|
||||
lattice_rvars(self, a, b)
|
||||
}
|
||||
|
||||
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
|
||||
lattice_var_t(self, self.infcx().rb,
|
||||
v_id, r,
|
||||
{|x, y| self.regions(x, y) })
|
||||
}
|
||||
|
||||
(f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
|
||||
(ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
|
||||
// for GLB, the scope is within the function and the free
|
||||
// region is always a parameter to the method. So the GLB
|
||||
// must be the scope.
|
||||
ok(b) // NDM--not so for nested functions
|
||||
(ty::re_free(f_id, _), s @ ty::re_scope(s_id)) |
|
||||
(s @ ty::re_scope(s_id), ty::re_free(f_id, _)) {
|
||||
// For GLB, generally the scope is within the fn and
|
||||
// the free region is a parameter to the fn. In that case,
|
||||
// the scope is always shorter than the free region.
|
||||
//
|
||||
// However, with nested fns, it can happen that the
|
||||
// scope surrounds the fn itself. In that case, we do
|
||||
// not know which will live longer---it depends on the
|
||||
// value provided for the free region in any given
|
||||
// call. And so we cannot give a GLB.
|
||||
let rm = self.infcx().tcx.region_map;
|
||||
alt region::nearest_common_ancestor(rm, f_id, s_id) {
|
||||
some(r_id) if r_id == f_id { ok(s) }
|
||||
_ { err(ty::terr_regions_differ(b, a)) }
|
||||
}
|
||||
}
|
||||
|
||||
(ty::re_scope(a_id), ty::re_scope(b_id)) {
|
||||
@ -1704,6 +1711,34 @@ fn lattice_tys<L:lattice_ops combine>(
|
||||
}
|
||||
}
|
||||
|
||||
// Pull out some common code from LUB/GLB for handling region vars:
|
||||
fn lattice_rvars<L:lattice_ops combine>(
|
||||
self: L, a: ty::region, b: ty::region) -> cres<ty::region> {
|
||||
|
||||
alt (a, b) {
|
||||
(ty::re_var(a_id), ty::re_var(b_id)) {
|
||||
lattice_vars(self, self.infcx().rb,
|
||||
a, a_id, b_id,
|
||||
{|x, y| self.regions(x, y) })
|
||||
}
|
||||
|
||||
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
|
||||
lattice_var_t(self, self.infcx().rb,
|
||||
v_id, r,
|
||||
{|x, y| self.regions(x, y) })
|
||||
}
|
||||
|
||||
_ {
|
||||
self.infcx().tcx.sess.bug(
|
||||
#fmt["%s: lattice_rvars invoked with a=%s and b=%s, \
|
||||
neither of which are region variables",
|
||||
self.tag(),
|
||||
a.to_str(self.infcx()),
|
||||
b.to_str(self.infcx())]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
|
||||
self: L, vb: vals_and_bindings<V, T>,
|
||||
a_t: T, a_vid: V, b_vid: V,
|
||||
|
@ -2078,8 +2078,8 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> str {
|
||||
ty_constr_to_str(a_constr);
|
||||
}
|
||||
terr_regions_differ(subregion, superregion) {
|
||||
ret #fmt("references with lifetime %s do not outlive references with \
|
||||
lifetime %s",
|
||||
ret #fmt("references with lifetime %s do not necessarily \
|
||||
outlive references with lifetime %s",
|
||||
region_to_str(cx, subregion),
|
||||
region_to_str(cx, superregion));
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// xfail-test
|
||||
|
||||
fn ignore<T>(t: T) {}
|
||||
|
||||
fn nested(x: &x.int) {
|
||||
@ -9,13 +7,13 @@ fn nested(x: &x.int) {
|
||||
ignore(fn&(z: &z.int) {
|
||||
ay = x;
|
||||
ay = &y;
|
||||
ay = z; //! ERROR foo
|
||||
ay = z; //! ERROR references with lifetime
|
||||
});
|
||||
|
||||
ignore(fn&(z: &z.int) -> &z.int {
|
||||
if false { ret x; } //! ERROR bar
|
||||
if false { ret &y; } //! ERROR bar
|
||||
if false { ret ay; } //! ERROR bar
|
||||
if false { ret x; } //! ERROR references with lifetime
|
||||
if false { ret &y; } //! ERROR references with lifetime
|
||||
if false { ret ay; } //! ERROR references with lifetime
|
||||
ret z;
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user