Skip to content

Commit f7efc29

Browse files
committed
rustc: Determine regions for locals
1 parent e968672 commit f7efc29

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/rustc/middle/regionck.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ import middle::ty;
88
import std::map::hashmap;
99
import syntax::{ast, visit};
1010

11+
// An "extended region", which includes the ordinarily-unnamed reference-
12+
// counted heap and exchange heap regions. This is used to detect borrowing.
13+
enum region_ext {
14+
re_rc,
15+
re_exheap,
16+
re_region(ty::region)
17+
}
18+
1119
type ctxt = {
1220
tcx: ty::ctxt,
1321
enclosing_block: option<ast::node_id>

src/rustc/middle/typeck.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,45 @@ fn lookup_field_ty(cx: ty::ctxt, items:[@ast::class_item],
18481848
cx.sess.span_fatal(sp, #fmt("unbound field %s", fieldname));
18491849
}
18501850

1851+
/*
1852+
* Returns the region that the value named by the given expression lives in.
1853+
* If the expression is not an lvalue, reports an error and returns the block
1854+
* region.
1855+
*
1856+
* Note that borrowing is not detected here, because we would have to
1857+
* immediately structurally resolve too many types otherwise. Thus the
1858+
* reference-counted heap and exchange heap regions will be reported as block
1859+
* regions instead. This is cleaned up in the region checking pass.
1860+
*/
1861+
fn region_of(fcx: @fn_ctxt, expr: @ast::expr) -> ty::region {
1862+
alt expr.node {
1863+
ast::expr_path(path) {
1864+
let defn = lookup_def(fcx, path.span, expr.id);
1865+
alt defn {
1866+
ast::def_local(local_id, _) |
1867+
ast::def_upvar(local_id, _, _) {
1868+
let local_blocks = fcx.ccx.tcx.region_map.local_blocks;
1869+
let local_block_id = local_blocks.get(local_id);
1870+
ret ty::re_block(local_block_id);
1871+
}
1872+
_ {
1873+
fcx.ccx.tcx.sess.span_unimpl(expr.span,
1874+
"immortal region");
1875+
}
1876+
}
1877+
}
1878+
ast::expr_field(base, _, _) | ast::expr_index(base, _) |
1879+
ast::expr_unary(ast::deref, base) {
1880+
fcx.ccx.tcx.sess.span_unimpl(expr.span, "regions of field, " +
1881+
"index, or deref operations");
1882+
}
1883+
_ {
1884+
fcx.ccx.tcx.sess.span_err(expr.span, "not an lvalue");
1885+
ret ty::re_block(0);
1886+
}
1887+
}
1888+
}
1889+
18511890
fn check_expr_fn_with_unifier(fcx: @fn_ctxt,
18521891
expr: @ast::expr,
18531892
proto: ast::proto,
@@ -2202,9 +2241,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
22022241
bot = check_expr(fcx, oper);
22032242
let oper_t = expr_ty(tcx, oper);
22042243

2205-
// FIXME: This is incorrect. Infer the proper region.
2244+
let region = region_of(fcx, oper);
22062245
let tm = { ty: oper_t, mutbl: mutbl };
2207-
oper_t = ty::mk_rptr(tcx, ty::re_block(0), tm);
2246+
oper_t = ty::mk_rptr(tcx, region, tm);
22082247
write_ty(tcx, id, oper_t);
22092248
}
22102249
ast::expr_path(pth) {

0 commit comments

Comments
 (0)