Skip to content

Commit 6b549f9

Browse files
committed
repair LUB/GLB of free/scope regions, and enable test
1 parent 58f8cb3 commit 6b549f9

File tree

3 files changed

+74
-41
lines changed

3 files changed

+74
-41
lines changed

src/rustc/middle/infer.rs

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,23 +1373,28 @@ impl of combine for lub {
13731373
ok(ty::re_static) // nothing lives longer than static
13741374
}
13751375

1376-
(ty::re_var(a_id), ty::re_var(b_id)) {
1377-
lattice_vars(self, self.infcx().rb,
1378-
a, a_id, b_id,
1379-
{|x, y| self.regions(x, y) })
1380-
}
1381-
1382-
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
1383-
lattice_var_t(self, self.infcx().rb,
1384-
v_id, r,
1385-
{|x, y| self.regions(x, y) })
1376+
(ty::re_var(_), _) | (_, ty::re_var(_)) {
1377+
lattice_rvars(self, a, b)
13861378
}
13871379

1388-
(f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
1389-
(ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
1390-
// for LUB, the scope is within the function and the free
1391-
// region is always a parameter to the method.
1392-
ok(f) // NDM--not so for nested functions
1380+
(f @ ty::re_free(f_id, _), ty::re_scope(s_id)) |
1381+
(ty::re_scope(s_id), f @ ty::re_free(f_id, _)) {
1382+
// For LUB, generally the scope is within the fn and
1383+
// the free region is a parameter to the fn. In that case,
1384+
// the free region will always live as long as the fn,
1385+
// which is longer than the scope.
1386+
//
1387+
// However, with nested fns, it can happen that the
1388+
// scope surrounds the fn itself. In that case, we do
1389+
// not know which will live longer---it depends on the
1390+
// value provided for the free region in any given
1391+
// call. And so we must just back off to re_static as
1392+
// the LUB.
1393+
let rm = self.infcx().tcx.region_map;
1394+
alt region::nearest_common_ancestor(rm, f_id, s_id) {
1395+
some(r_id) if r_id == f_id { ok(f) }
1396+
_ { ok(ty::re_static) }
1397+
}
13931398
}
13941399

13951400
(ty::re_scope(a_id), ty::re_scope(b_id)) {
@@ -1399,7 +1404,7 @@ impl of combine for lub {
13991404
let rm = self.infcx().tcx.region_map;
14001405
alt region::nearest_common_ancestor(rm, a_id, b_id) {
14011406
some(r_id) { ok(ty::re_scope(r_id)) }
1402-
_ { err(ty::terr_regions_differ(b, a)) }
1407+
_ { ok(ty::re_static) }
14031408
}
14041409
}
14051410

@@ -1414,7 +1419,7 @@ impl of combine for lub {
14141419
if a == b {
14151420
ok(a)
14161421
} else {
1417-
err(ty::terr_regions_differ(b, a))
1422+
ok(ty::re_static)
14181423
}
14191424
}
14201425
}
@@ -1551,24 +1556,26 @@ impl of combine for glb {
15511556
ok(r)
15521557
}
15531558

1554-
(ty::re_var(a_id), ty::re_var(b_id)) {
1555-
lattice_vars(self, self.infcx().rb,
1556-
a, a_id, b_id,
1557-
{|x, y| self.regions(x, y) })
1558-
}
1559-
1560-
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
1561-
lattice_var_t(self, self.infcx().rb,
1562-
v_id, r,
1563-
{|x, y| self.regions(x, y) })
1559+
(ty::re_var(_), _) | (_, ty::re_var(_)) {
1560+
lattice_rvars(self, a, b)
15641561
}
15651562

1566-
(f @ ty::re_free(f_id, f_br), ty::re_scope(s_id)) |
1567-
(ty::re_scope(s_id), f @ ty::re_free(f_id, f_br)) {
1568-
// for GLB, the scope is within the function and the free
1569-
// region is always a parameter to the method. So the GLB
1570-
// must be the scope.
1571-
ok(b) // NDM--not so for nested functions
1563+
(ty::re_free(f_id, _), s @ ty::re_scope(s_id)) |
1564+
(s @ ty::re_scope(s_id), ty::re_free(f_id, _)) {
1565+
// For GLB, generally the scope is within the fn and
1566+
// the free region is a parameter to the fn. In that case,
1567+
// the scope is always shorter than the free region.
1568+
//
1569+
// However, with nested fns, it can happen that the
1570+
// scope surrounds the fn itself. In that case, we do
1571+
// not know which will live longer---it depends on the
1572+
// value provided for the free region in any given
1573+
// call. And so we cannot give a GLB.
1574+
let rm = self.infcx().tcx.region_map;
1575+
alt region::nearest_common_ancestor(rm, f_id, s_id) {
1576+
some(r_id) if r_id == f_id { ok(s) }
1577+
_ { err(ty::terr_regions_differ(b, a)) }
1578+
}
15721579
}
15731580

15741581
(ty::re_scope(a_id), ty::re_scope(b_id)) {
@@ -1704,6 +1711,34 @@ fn lattice_tys<L:lattice_ops combine>(
17041711
}
17051712
}
17061713

1714+
// Pull out some common code from LUB/GLB for handling region vars:
1715+
fn lattice_rvars<L:lattice_ops combine>(
1716+
self: L, a: ty::region, b: ty::region) -> cres<ty::region> {
1717+
1718+
alt (a, b) {
1719+
(ty::re_var(a_id), ty::re_var(b_id)) {
1720+
lattice_vars(self, self.infcx().rb,
1721+
a, a_id, b_id,
1722+
{|x, y| self.regions(x, y) })
1723+
}
1724+
1725+
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) {
1726+
lattice_var_t(self, self.infcx().rb,
1727+
v_id, r,
1728+
{|x, y| self.regions(x, y) })
1729+
}
1730+
1731+
_ {
1732+
self.infcx().tcx.sess.bug(
1733+
#fmt["%s: lattice_rvars invoked with a=%s and b=%s, \
1734+
neither of which are region variables",
1735+
self.tag(),
1736+
a.to_str(self.infcx()),
1737+
b.to_str(self.infcx())]);
1738+
}
1739+
}
1740+
}
1741+
17071742
fn lattice_vars<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
17081743
self: L, vb: vals_and_bindings<V, T>,
17091744
a_t: T, a_vid: V, b_vid: V,

src/rustc/middle/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,8 +2078,8 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> str {
20782078
ty_constr_to_str(a_constr);
20792079
}
20802080
terr_regions_differ(subregion, superregion) {
2081-
ret #fmt("references with lifetime %s do not outlive references with \
2082-
lifetime %s",
2081+
ret #fmt("references with lifetime %s do not necessarily \
2082+
outlive references with lifetime %s",
20832083
region_to_str(cx, subregion),
20842084
region_to_str(cx, superregion));
20852085
}

src/test/compile-fail/regions-nested-fns.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// xfail-test
2-
31
fn ignore<T>(t: T) {}
42

53
fn nested(x: &x.int) {
@@ -9,13 +7,13 @@ fn nested(x: &x.int) {
97
ignore(fn&(z: &z.int) {
108
ay = x;
119
ay = &y;
12-
ay = z; //! ERROR foo
10+
ay = z; //! ERROR references with lifetime
1311
});
1412

1513
ignore(fn&(z: &z.int) -> &z.int {
16-
if false { ret x; } //! ERROR bar
17-
if false { ret &y; } //! ERROR bar
18-
if false { ret ay; } //! ERROR bar
14+
if false { ret x; } //! ERROR references with lifetime
15+
if false { ret &y; } //! ERROR references with lifetime
16+
if false { ret ay; } //! ERROR references with lifetime
1917
ret z;
2018
});
2119
}

0 commit comments

Comments
 (0)