rustc: Determine regions for locals
This commit is contained in:
parent
e968672ac7
commit
f7efc29b38
2 changed files with 49 additions and 2 deletions
|
@ -8,6 +8,14 @@ import middle::ty;
|
||||||
import std::map::hashmap;
|
import std::map::hashmap;
|
||||||
import syntax::{ast, visit};
|
import syntax::{ast, visit};
|
||||||
|
|
||||||
|
// An "extended region", which includes the ordinarily-unnamed reference-
|
||||||
|
// counted heap and exchange heap regions. This is used to detect borrowing.
|
||||||
|
enum region_ext {
|
||||||
|
re_rc,
|
||||||
|
re_exheap,
|
||||||
|
re_region(ty::region)
|
||||||
|
}
|
||||||
|
|
||||||
type ctxt = {
|
type ctxt = {
|
||||||
tcx: ty::ctxt,
|
tcx: ty::ctxt,
|
||||||
enclosing_block: option<ast::node_id>
|
enclosing_block: option<ast::node_id>
|
||||||
|
|
|
@ -1848,6 +1848,45 @@ fn lookup_field_ty(cx: ty::ctxt, items:[@ast::class_item],
|
||||||
cx.sess.span_fatal(sp, #fmt("unbound field %s", fieldname));
|
cx.sess.span_fatal(sp, #fmt("unbound field %s", fieldname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the region that the value named by the given expression lives in.
|
||||||
|
* If the expression is not an lvalue, reports an error and returns the block
|
||||||
|
* region.
|
||||||
|
*
|
||||||
|
* Note that borrowing is not detected here, because we would have to
|
||||||
|
* immediately structurally resolve too many types otherwise. Thus the
|
||||||
|
* reference-counted heap and exchange heap regions will be reported as block
|
||||||
|
* regions instead. This is cleaned up in the region checking pass.
|
||||||
|
*/
|
||||||
|
fn region_of(fcx: @fn_ctxt, expr: @ast::expr) -> ty::region {
|
||||||
|
alt expr.node {
|
||||||
|
ast::expr_path(path) {
|
||||||
|
let defn = lookup_def(fcx, path.span, expr.id);
|
||||||
|
alt defn {
|
||||||
|
ast::def_local(local_id, _) |
|
||||||
|
ast::def_upvar(local_id, _, _) {
|
||||||
|
let local_blocks = fcx.ccx.tcx.region_map.local_blocks;
|
||||||
|
let local_block_id = local_blocks.get(local_id);
|
||||||
|
ret ty::re_block(local_block_id);
|
||||||
|
}
|
||||||
|
_ {
|
||||||
|
fcx.ccx.tcx.sess.span_unimpl(expr.span,
|
||||||
|
"immortal region");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast::expr_field(base, _, _) | ast::expr_index(base, _) |
|
||||||
|
ast::expr_unary(ast::deref, base) {
|
||||||
|
fcx.ccx.tcx.sess.span_unimpl(expr.span, "regions of field, " +
|
||||||
|
"index, or deref operations");
|
||||||
|
}
|
||||||
|
_ {
|
||||||
|
fcx.ccx.tcx.sess.span_err(expr.span, "not an lvalue");
|
||||||
|
ret ty::re_block(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
|
fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
|
||||||
expr: @ast::expr,
|
expr: @ast::expr,
|
||||||
proto: ast::proto,
|
proto: ast::proto,
|
||||||
|
@ -2202,9 +2241,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||||
bot = check_expr(fcx, oper);
|
bot = check_expr(fcx, oper);
|
||||||
let oper_t = expr_ty(tcx, oper);
|
let oper_t = expr_ty(tcx, oper);
|
||||||
|
|
||||||
// FIXME: This is incorrect. Infer the proper region.
|
let region = region_of(fcx, oper);
|
||||||
let tm = { ty: oper_t, mutbl: mutbl };
|
let tm = { ty: oper_t, mutbl: mutbl };
|
||||||
oper_t = ty::mk_rptr(tcx, ty::re_block(0), tm);
|
oper_t = ty::mk_rptr(tcx, region, tm);
|
||||||
write_ty(tcx, id, oper_t);
|
write_ty(tcx, id, oper_t);
|
||||||
}
|
}
|
||||||
ast::expr_path(pth) {
|
ast::expr_path(pth) {
|
||||||
|
|
Loading…
Reference in a new issue