Skip to content

Commit 3062f9f

Browse files
committed
---
yaml --- r: 15819 b: refs/heads/try c: 9c7b74b h: refs/heads/master i: 15817: 2f2f145 15815: 6c6a973 v: v3
1 parent 20f6ccf commit 3062f9f

File tree

9 files changed

+116
-72
lines changed

9 files changed

+116
-72
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: 7df7a9d8ac29f2e9498e109c16ba4c9241b4c1ae
5+
refs/heads/try: 9c7b74b025e151647f4e009484257f069553fd32
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/rustc/middle/borrowck.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ impl methods for check_loan_ctxt {
465465
fn walk_loans(scope_id: ast::node_id,
466466
f: fn(loan) -> bool) {
467467
let mut scope_id = scope_id;
468-
let parents = self.tcx().region_map.parents;
468+
let region_map = self.tcx().region_map;
469469
let req_loan_map = self.req_loan_map;
470470

471471
loop {
@@ -477,7 +477,7 @@ impl methods for check_loan_ctxt {
477477
}
478478
}
479479

480-
alt parents.find(scope_id) {
480+
alt region_map.find(scope_id) {
481481
none { ret; }
482482
some(next_scope_id) { scope_id = next_scope_id; }
483483
}
@@ -570,7 +570,7 @@ impl methods for check_loan_ctxt {
570570
some(loanss) { loanss }
571571
};
572572

573-
let par_scope_id = self.tcx().region_map.parents.get(scope_id);
573+
let par_scope_id = self.tcx().region_map.get(scope_id);
574574
for self.walk_loans(par_scope_id) { |old_loan|
575575
for (*new_loanss).each { |new_loans|
576576
for (*new_loans).each { |new_loan|

branches/try/src/rustc/middle/region.rs

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,16 @@ type binding = {node_id: ast::node_id,
151151
name: str,
152152
br: ty::bound_region};
153153

154-
type region_map = {
155-
// Mapping from a block/function expression to its parent.
156-
parents: hashmap<ast::node_id,ast::node_id>,
157-
158-
// Mapping from arguments and local variables to the block in
159-
// which they are declared. Arguments are considered to be declared
160-
// within the body of the function.
161-
local_blocks: hashmap<ast::node_id,ast::node_id>
162-
};
154+
// Mapping from a block/expr/binding to the innermost scope that
155+
// bounds its lifetime. For a block/expression, this is the lifetime
156+
// in which it will be evaluated. For a binding, this is the lifetime
157+
// in which is in scope.
158+
type region_map = hashmap<ast::node_id, ast::node_id>;
163159

164160
type ctxt = {
165161
sess: session,
166162
def_map: resolve::def_map,
167-
region_map: @region_map,
163+
region_map: region_map,
168164

169165
// These two fields (parent and closure_parent) specify the parent
170166
// scope of the current expression. The parent scope is the
@@ -207,27 +203,27 @@ type ctxt = {
207203

208204
// Returns true if `subscope` is equal to or is lexically nested inside
209205
// `superscope` and false otherwise.
210-
fn scope_contains(region_map: @region_map, superscope: ast::node_id,
206+
fn scope_contains(region_map: region_map, superscope: ast::node_id,
211207
subscope: ast::node_id) -> bool {
212208
let mut subscope = subscope;
213209
while superscope != subscope {
214-
alt region_map.parents.find(subscope) {
210+
alt region_map.find(subscope) {
215211
none { ret false; }
216212
some(scope) { subscope = scope; }
217213
}
218214
}
219215
ret true;
220216
}
221217

222-
fn nearest_common_ancestor(region_map: @region_map, scope_a: ast::node_id,
218+
fn nearest_common_ancestor(region_map: region_map, scope_a: ast::node_id,
223219
scope_b: ast::node_id) -> option<ast::node_id> {
224220

225-
fn ancestors_of(region_map: @region_map, scope: ast::node_id)
221+
fn ancestors_of(region_map: region_map, scope: ast::node_id)
226222
-> [ast::node_id] {
227223
let mut result = [scope];
228224
let mut scope = scope;
229225
loop {
230-
alt region_map.parents.find(scope) {
226+
alt region_map.find(scope) {
231227
none { ret result; }
232228
some(superscope) {
233229
result += [superscope];
@@ -285,7 +281,7 @@ fn record_parent(cx: ctxt, child_id: ast::node_id) {
285281
none { /* no-op */ }
286282
some(parent_id) {
287283
#debug["parent of node %d is node %d", child_id, parent_id];
288-
cx.region_map.parents.insert(child_id, parent_id);
284+
cx.region_map.insert(child_id, parent_id);
289285
}
290286
}
291287
}
@@ -314,8 +310,7 @@ fn resolve_pat(pat: @ast::pat, cx: ctxt, visitor: visit::vt<ctxt>) {
314310
}
315311
_ {
316312
/* This names a local. Bind it to the containing scope. */
317-
let local_blocks = cx.region_map.local_blocks;
318-
local_blocks.insert(pat.id, parent_id(cx, pat.span));
313+
record_parent(cx, pat.id);
319314
}
320315
}
321316
}
@@ -357,8 +352,7 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
357352
}
358353

359354
fn resolve_local(local: @ast::local, cx: ctxt, visitor: visit::vt<ctxt>) {
360-
cx.region_map.local_blocks.insert(
361-
local.node.id, parent_id(cx, local.span));
355+
record_parent(cx, local.node.id);
362356
visit::visit_local(local, cx, visitor);
363357
}
364358

@@ -391,19 +385,17 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
391385
cx.closure_parent, fn_cx.parent];
392386

393387
for decl.inputs.each { |input|
394-
cx.region_map.local_blocks.insert(
395-
input.id, body.node.id);
388+
cx.region_map.insert(input.id, body.node.id);
396389
}
397390

398391
visit::visit_fn(fk, decl, body, sp, id, fn_cx, visitor);
399392
}
400393

401394
fn resolve_crate(sess: session, def_map: resolve::def_map, crate: @ast::crate)
402-
-> @region_map {
395+
-> region_map {
403396
let cx: ctxt = {sess: sess,
404397
def_map: def_map,
405-
region_map: @{parents: map::int_hash(),
406-
local_blocks: map::int_hash()},
398+
region_map: map::int_hash(),
407399
parent: none,
408400
closure_parent: none};
409401
let visitor = visit::mk_vt(@{

branches/try/src/rustc/middle/ty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ type ctxt =
206206
mut next_id: uint,
207207
sess: session::session,
208208
def_map: resolve::def_map,
209-
region_map: @middle::region::region_map,
209+
region_map: middle::region::region_map,
210210

211211
// Stores the types for various nodes in the AST. Note that this table
212212
// is not guaranteed to be populated until after typeck. See
@@ -459,7 +459,7 @@ fn new_ty_hash<V: copy>() -> map::hashmap<t, V> {
459459

460460
fn mk_ctxt(s: session::session, dm: resolve::def_map, amap: ast_map::map,
461461
freevars: freevars::freevar_map,
462-
region_map: @middle::region::region_map) -> ctxt {
462+
region_map: middle::region::region_map) -> ctxt {
463463
let interner = map::hashmap({|&&k: intern_key|
464464
hash_type_structure(k.struct) +
465465
option::map_default(k.o_def_id, 0u, ast_util::hash_def_id)
@@ -688,7 +688,7 @@ fn default_arg_mode_for_ty(ty: ty::t) -> ast::rmode {
688688
// Returns the narrowest lifetime enclosing the evaluation of the expression
689689
// with id `id`.
690690
fn encl_region(cx: ctxt, id: ast::node_id) -> ty::region {
691-
alt cx.region_map.parents.find(id) {
691+
alt cx.region_map.find(id) {
692692
some(encl_scope) {ty::re_scope(encl_scope)}
693693
none {ty::re_static}
694694
}

branches/try/src/rustc/middle/typeck.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,9 +1577,8 @@ fn region_of(fcx: @fn_ctxt, expr: @ast::expr) -> ty::region {
15771577
alt defn {
15781578
ast::def_local(local_id, _) |
15791579
ast::def_upvar(local_id, _, _) {
1580-
let local_blocks = fcx.ccx.tcx.region_map.local_blocks;
1581-
let local_block_id = local_blocks.get(local_id);
1582-
ty::re_scope(local_block_id)
1580+
let local_scope = fcx.ccx.tcx.region_map.get(local_id);
1581+
ty::re_scope(local_scope)
15831582
}
15841583
_ {
15851584
ty::re_static
@@ -2629,8 +2628,7 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
26292628
}
26302629

26312630
let region =
2632-
ty::re_scope(
2633-
fcx.ccx.tcx.region_map.local_blocks.get(local.node.id));
2631+
ty::re_scope(fcx.ccx.tcx.region_map.get(local.node.id));
26342632
let pcx = {
26352633
fcx: fcx,
26362634
map: pat_id_map(fcx.ccx.tcx.def_map, local.node.pat),

branches/try/src/rustc/middle/typeck/regionck.rs

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,24 @@ the region scope `r`.
1616
import util::ppaux;
1717
import syntax::print::pprust;
1818

19+
type rcx = @{fcx: @fn_ctxt, mut errors_reported: uint};
20+
type rvt = visit::vt<rcx>;
21+
1922
fn regionck_expr(fcx: @fn_ctxt, e: @ast::expr) {
20-
let v = regionck_visitor(fcx);
21-
v.visit_expr(e, fcx, v);
23+
let rcx = @{fcx:fcx, mut errors_reported: 0u};
24+
let v = regionck_visitor();
25+
v.visit_expr(e, rcx, v);
2226
}
2327

2428
fn regionck_fn(fcx: @fn_ctxt,
2529
_decl: ast::fn_decl,
2630
blk: ast::blk) {
27-
let v = regionck_visitor(fcx);
28-
v.visit_block(blk, fcx, v);
31+
let rcx = @{fcx:fcx, mut errors_reported: 0u};
32+
let v = regionck_visitor();
33+
v.visit_block(blk, rcx, v);
2934
}
3035

31-
type rvt = visit::vt<@fn_ctxt>;
32-
33-
fn regionck_visitor(_fcx: @fn_ctxt) -> rvt {
36+
fn regionck_visitor() -> rvt {
3437
visit::mk_vt(@{visit_item: visit_item,
3538
visit_stmt: visit_stmt,
3639
visit_expr: visit_expr,
@@ -40,67 +43,106 @@ fn regionck_visitor(_fcx: @fn_ctxt) -> rvt {
4043
with *visit::default_visitor()})
4144
}
4245

43-
fn visit_item(_item: @ast::item, &&_fcx: @fn_ctxt, _v: rvt) {
46+
fn visit_item(_item: @ast::item, &&_rcx: rcx, _v: rvt) {
4447
// Ignore items
4548
}
4649

47-
fn visit_local(l: @ast::local, &&fcx: @fn_ctxt, v: rvt) {
48-
visit::visit_local(l, fcx, v);
50+
fn visit_local(l: @ast::local, &&rcx: rcx, v: rvt) {
51+
let e = rcx.errors_reported;
52+
v.visit_pat(l.node.pat, rcx, v);
53+
if e != rcx.errors_reported {
54+
ret; // if decl has errors, skip initializer expr
55+
}
56+
57+
v.visit_ty(l.node.ty, rcx, v);
58+
for l.node.init.each { |i|
59+
v.visit_expr(i.expr, rcx, v);
60+
}
4961
}
5062

51-
fn visit_pat(p: @ast::pat, &&fcx: @fn_ctxt, v: rvt) {
52-
visit::visit_pat(p, fcx, v);
63+
fn visit_pat(p: @ast::pat, &&rcx: rcx, v: rvt) {
64+
let fcx = rcx.fcx;
65+
alt p.node {
66+
ast::pat_ident(path, _)
67+
if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) {
68+
#debug["visit_pat binding=%s", path.idents[0]];
69+
visit_node(p.id, p.span, rcx);
70+
}
71+
_ {}
72+
}
73+
74+
visit::visit_pat(p, rcx, v);
5375
}
5476

55-
fn visit_block(b: ast::blk, &&fcx: @fn_ctxt, v: rvt) {
56-
visit::visit_block(b, fcx, v);
77+
fn visit_block(b: ast::blk, &&rcx: rcx, v: rvt) {
78+
visit::visit_block(b, rcx, v);
5779
}
5880

59-
fn visit_expr(e: @ast::expr, &&fcx: @fn_ctxt, v: rvt) {
81+
fn visit_expr(e: @ast::expr, &&rcx: rcx, v: rvt) {
6082
#debug["visit_expr(e=%s)", pprust::expr_to_str(e)];
6183

62-
visit_ty(fcx.expr_ty(e), e.id, e.span, fcx);
63-
visit::visit_expr(e, fcx, v);
84+
alt e.node {
85+
ast::expr_path(*) {
86+
// Avoid checking the use of local variables, as we already
87+
// check their definitions. The def'n always encloses the
88+
// use. So if the def'n is enclosed by the region, then the
89+
// uses will also be enclosed (and otherwise, an error will
90+
// have been reported at the def'n site).
91+
alt lookup_def(rcx.fcx, e.span, e.id) {
92+
ast::def_local(*) | ast::def_arg(*) | ast::def_upvar(*) { ret; }
93+
_ { }
94+
}
95+
}
96+
_ { }
97+
}
98+
99+
if !visit_node(e.id, e.span, rcx) { ret; }
100+
visit::visit_expr(e, rcx, v);
64101
}
65102

66-
fn visit_stmt(s: @ast::stmt, &&fcx: @fn_ctxt, v: rvt) {
67-
visit::visit_stmt(s, fcx, v);
103+
fn visit_stmt(s: @ast::stmt, &&rcx: rcx, v: rvt) {
104+
visit::visit_stmt(s, rcx, v);
68105
}
69106

70-
fn visit_ty(ty: ty::t,
71-
id: ast::node_id,
72-
span: span,
73-
fcx: @fn_ctxt) {
107+
// checks the type of the node `id` and reports an error if it
108+
// references a region that is not in scope for that node. Returns
109+
// false if an error is reported; this is used to cause us to cut off
110+
// region checking for that subtree to avoid reporting tons of errors.
111+
fn visit_node(id: ast::node_id, span: span, rcx: rcx) -> bool {
112+
let fcx = rcx.fcx;
74113

75114
// Try to resolve the type. If we encounter an error, then typeck
76115
// is going to fail anyway, so just stop here and let typeck
77116
// report errors later on in the writeback phase.
78-
let ty = alt infer::resolve_deep(fcx.infcx, ty, false) {
79-
result::err(_) { ret; }
117+
let ty0 = fcx.node_ty(id);
118+
let ty = alt infer::resolve_deep(fcx.infcx, ty0, false) {
119+
result::err(_) { ret true; }
80120
result::ok(ty) { ty }
81121
};
82122

83123
// find the region where this expr evaluation is taking place
84124
let tcx = fcx.ccx.tcx;
85125
let encl_region = ty::encl_region(tcx, id);
86126

87-
#debug["visit_ty(ty=%s, id=%d, encl_region=%s)",
127+
#debug["visit_node(ty=%s, id=%d, encl_region=%s, ty0=%s)",
88128
ppaux::ty_to_str(tcx, ty),
89129
id,
90-
ppaux::region_to_str(tcx, encl_region)];
130+
ppaux::region_to_str(tcx, encl_region),
131+
ppaux::ty_to_str(tcx, ty0)];
91132

92133
// Otherwise, look at the type and see if it is a region pointer.
93-
if !ty::type_has_regions(ty) { ret; }
134+
let e = rcx.errors_reported;
94135
ty::walk_regions_and_ty(
95136
tcx, ty,
96-
{ |r| constrain_region(fcx, encl_region, span, r); },
137+
{ |r| constrain_region(rcx, encl_region, span, r); },
97138
{ |t| ty::type_has_regions(t) });
139+
ret (e == rcx.errors_reported);
98140

99-
fn constrain_region(fcx: @fn_ctxt,
141+
fn constrain_region(rcx: rcx,
100142
encl_region: ty::region,
101143
span: span,
102144
region: ty::region) {
103-
let tcx = fcx.ccx.tcx;
145+
let tcx = rcx.fcx.ccx.tcx;
104146

105147
#debug["constrain_region(encl_region=%s, region=%s)",
106148
ppaux::region_to_str(tcx, encl_region),
@@ -117,13 +159,14 @@ fn visit_ty(ty: ty::t,
117159
_ {}
118160
}
119161

120-
alt fcx.mk_subr(encl_region, region) {
162+
alt rcx.fcx.mk_subr(encl_region, region) {
121163
result::err(_) {
122164
tcx.sess.span_err(
123165
span,
124166
#fmt["reference is not valid outside \
125167
of its lifetime, %s",
126168
ppaux::region_to_str(tcx, region)]);
169+
rcx.errors_reported += 1u;
127170
}
128171
result::ok(()) {
129172
}

branches/try/src/test/compile-fail/regions-borrow.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ fn main() {
55
let r = foo(p);
66
//!^ ERROR reference is not valid
77
assert *p == *r;
8-
//!^ ERROR reference is not valid
98
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn main() {
2+
let x = 3;
3+
4+
// Here, the variable `p` gets inferred to a type with a lifetime
5+
// of the loop body. The regionck then determines that this type
6+
// is invalid.
7+
let mut p = //! ERROR reference is not valid
8+
&x;
9+
10+
loop {
11+
let x = 1 + *p;
12+
p = &x;
13+
}
14+
}

0 commit comments

Comments
 (0)