From 3e8bb22af17f7c97e2513ac4d99323dcb46ca6fe Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Sun, 11 Mar 2012 13:28:43 -0700 Subject: [PATCH] rustc: Unify regions in most cases. (Nested functions aren't properly handled yet.) --- src/rustc/middle/region.rs | 14 ++++++++++ src/rustc/middle/ty.rs | 53 +++++++++++++++++++++++++++++++++++--- src/rustc/middle/typeck.rs | 5 ++-- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index 303ad24513d..90be3f5b12e 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -43,6 +43,20 @@ type ctxt = { parent: parent }; +// Returns true if `subblock` is equal to or is lexically nested inside +// `superblock` and false otherwise. +fn block_contains(region_map: @region_map, superblock: ast::node_id, + subblock: ast::node_id) -> bool { + let subblock = subblock; + while superblock != subblock { + alt region_map.parent_blocks.find(subblock) { + none { ret false; } + some(blk) { subblock = blk; } + } + } + ret true; +} + fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt) { alt ty.node { ast::ty_rptr({id: region_id, node: node}, _) { diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 800caaf639c..a9a71f51100 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -283,6 +283,7 @@ enum type_err { terr_mode_mismatch(mode, mode), terr_constr_len(uint, uint), terr_constr_mismatch(@type_constr, @type_constr), + terr_regions_differ, } enum param_bound { @@ -1885,6 +1886,45 @@ mod unify { } } } + fn unify_regions(cx: @uctxt, e_region: region, a_region: region, + variance: variance) -> option { + let sub, super; + alt variance { + covariant { super = e_region; sub = a_region; } + contravariant { super = a_region; sub = e_region; } + invariant { + ret if e_region == a_region { some(e_region) } else { none }; + } + } + + alt (super, sub) { + (re_caller(_), re_caller(_)) { + // FIXME: This is wrong w/r/t nested functions. + ret some(super); + } + (re_caller(_), re_named(_)) | (re_named(_), re_caller(_)) { + ret none; + } + (re_named(a), re_named(b)) { + ret if a == b { some(super) } else { none } + } + (re_caller(_), re_block(_)) | (re_named(_), re_block(_)) { + // FIXME: This is wrong w/r/t nested functions. + ret some(super); + } + (re_block(_), re_caller(_)) | (re_block(_), re_named(_)) { + ret none; + } + (re_block(superblock), re_block(subblock)) { + if region::block_contains(cx.tcx.region_map, superblock, + subblock) { + ret some(super); + } else { + ret none; + } + } + } + } fn unify_step(cx: @uctxt, expected: t, actual: t, variance: variance) -> result { @@ -1943,9 +1983,13 @@ mod unify { unify_mt(cx, e_mt, a_mt, variance, terr_ptr_mutability, mk_ptr) } (ty_rptr(e_region, e_mt), ty_rptr(a_region, a_mt)) { - // TODO: Unify regions. Take covariance/invariance into account. - unify_mt(cx, e_mt, a_mt, variance, terr_ref_mutability, - bind mk_rptr(_, re_block(0), _)) + alt unify_regions(cx, e_region, a_region, variance) { + none { ures_err(terr_regions_differ) } + some(r_region) { + unify_mt(cx, e_mt, a_mt, variance, terr_ref_mutability, + bind mk_rptr(_, r_region, _)) + } + } } (ty_res(e_id, e_inner, e_tps), ty_res(a_id, a_inner, a_tps)) if e_id == a_id { @@ -2154,6 +2198,9 @@ fn type_err_to_str(err: type_err) -> str { " but found one with constraint " + ty_constr_to_str(a_constr); } + terr_regions_differ { + ret "inconsistent pointer lifetimes" + } } } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 728d9f82a75..7bc779429fb 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -319,8 +319,9 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { ast::ty_ptr(mt) { ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt)) } - ast::ty_rptr(_, mt) { - ty::mk_rptr(tcx, ty::re_block(0), ast_mt_to_mt(tcx, mode, mt)) + ast::ty_rptr(region, mt) { + let region = tcx.region_map.ast_type_to_region.get(region.id); + ty::mk_rptr(tcx, region, ast_mt_to_mt(tcx, mode, mt)) } ast::ty_tup(fields) { let flds = vec::map(fields, bind ast_ty_to_ty(tcx, mode, _));