Skip to content

Commit 3e8bb22

Browse files
committed
rustc: Unify regions in most cases. (Nested functions aren't properly handled yet.)
1 parent f7efc29 commit 3e8bb22

File tree

3 files changed

+67
-5
lines changed

3 files changed

+67
-5
lines changed

src/rustc/middle/region.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ type ctxt = {
4343
parent: parent
4444
};
4545

46+
// Returns true if `subblock` is equal to or is lexically nested inside
47+
// `superblock` and false otherwise.
48+
fn block_contains(region_map: @region_map, superblock: ast::node_id,
49+
subblock: ast::node_id) -> bool {
50+
let subblock = subblock;
51+
while superblock != subblock {
52+
alt region_map.parent_blocks.find(subblock) {
53+
none { ret false; }
54+
some(blk) { subblock = blk; }
55+
}
56+
}
57+
ret true;
58+
}
59+
4660
fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) {
4761
alt ty.node {
4862
ast::ty_rptr({id: region_id, node: node}, _) {

src/rustc/middle/ty.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ enum type_err {
283283
terr_mode_mismatch(mode, mode),
284284
terr_constr_len(uint, uint),
285285
terr_constr_mismatch(@type_constr, @type_constr),
286+
terr_regions_differ,
286287
}
287288

288289
enum param_bound {
@@ -1885,6 +1886,45 @@ mod unify {
18851886
}
18861887
}
18871888
}
1889+
fn unify_regions(cx: @uctxt, e_region: region, a_region: region,
1890+
variance: variance) -> option<region> {
1891+
let sub, super;
1892+
alt variance {
1893+
covariant { super = e_region; sub = a_region; }
1894+
contravariant { super = a_region; sub = e_region; }
1895+
invariant {
1896+
ret if e_region == a_region { some(e_region) } else { none };
1897+
}
1898+
}
1899+
1900+
alt (super, sub) {
1901+
(re_caller(_), re_caller(_)) {
1902+
// FIXME: This is wrong w/r/t nested functions.
1903+
ret some(super);
1904+
}
1905+
(re_caller(_), re_named(_)) | (re_named(_), re_caller(_)) {
1906+
ret none;
1907+
}
1908+
(re_named(a), re_named(b)) {
1909+
ret if a == b { some(super) } else { none }
1910+
}
1911+
(re_caller(_), re_block(_)) | (re_named(_), re_block(_)) {
1912+
// FIXME: This is wrong w/r/t nested functions.
1913+
ret some(super);
1914+
}
1915+
(re_block(_), re_caller(_)) | (re_block(_), re_named(_)) {
1916+
ret none;
1917+
}
1918+
(re_block(superblock), re_block(subblock)) {
1919+
if region::block_contains(cx.tcx.region_map, superblock,
1920+
subblock) {
1921+
ret some(super);
1922+
} else {
1923+
ret none;
1924+
}
1925+
}
1926+
}
1927+
}
18881928

18891929
fn unify_step(cx: @uctxt, expected: t, actual: t,
18901930
variance: variance) -> result {
@@ -1943,9 +1983,13 @@ mod unify {
19431983
unify_mt(cx, e_mt, a_mt, variance, terr_ptr_mutability, mk_ptr)
19441984
}
19451985
(ty_rptr(e_region, e_mt), ty_rptr(a_region, a_mt)) {
1946-
// TODO: Unify regions. Take covariance/invariance into account.
1947-
unify_mt(cx, e_mt, a_mt, variance, terr_ref_mutability,
1948-
bind mk_rptr(_, re_block(0), _))
1986+
alt unify_regions(cx, e_region, a_region, variance) {
1987+
none { ures_err(terr_regions_differ) }
1988+
some(r_region) {
1989+
unify_mt(cx, e_mt, a_mt, variance, terr_ref_mutability,
1990+
bind mk_rptr(_, r_region, _))
1991+
}
1992+
}
19491993
}
19501994
(ty_res(e_id, e_inner, e_tps), ty_res(a_id, a_inner, a_tps))
19511995
if e_id == a_id {
@@ -2154,6 +2198,9 @@ fn type_err_to_str(err: type_err) -> str {
21542198
" but found one with constraint " +
21552199
ty_constr_to_str(a_constr);
21562200
}
2201+
terr_regions_differ {
2202+
ret "inconsistent pointer lifetimes"
2203+
}
21572204
}
21582205
}
21592206

src/rustc/middle/typeck.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
319319
ast::ty_ptr(mt) {
320320
ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt))
321321
}
322-
ast::ty_rptr(_, mt) {
323-
ty::mk_rptr(tcx, ty::re_block(0), ast_mt_to_mt(tcx, mode, mt))
322+
ast::ty_rptr(region, mt) {
323+
let region = tcx.region_map.ast_type_to_region.get(region.id);
324+
ty::mk_rptr(tcx, region, ast_mt_to_mt(tcx, mode, mt))
324325
}
325326
ast::ty_tup(fields) {
326327
let flds = vec::map(fields, bind ast_ty_to_ty(tcx, mode, _));

0 commit comments

Comments
 (0)