Skip to content

Commit adb61e3

Browse files
committed
get preservation of boxes working, at least in simple cases
1 parent 4c7be32 commit adb61e3

File tree

11 files changed

+523
-306
lines changed

11 files changed

+523
-306
lines changed

src/rt/boxed_region.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ void boxed_region::free(rust_opaque_box *box) {
5454

5555
if (env->poison_on_free) {
5656
memset(box_body(box), 0xab, box->td->size);
57-
return;
5857
}
5958

6059
box->prev = NULL;

src/rustc/driver/driver.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
190190
bind middle::check_self::check_crate(ty_cx, crate));
191191
time(time_passes, "typestate checking",
192192
bind middle::tstate::ck::check_crate(ty_cx, crate));
193-
let (_root_map, mutbl_map) = time(
193+
let (root_map, mutbl_map) = time(
194194
time_passes, "borrow checking",
195195
bind middle::borrowck::check_crate(ty_cx, method_map, crate));
196196
time(time_passes, "region checking",
@@ -208,10 +208,10 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
208208
if upto == cu_no_trans { ret {crate: crate, tcx: some(ty_cx)}; }
209209
let outputs = option::get(outputs);
210210

211-
let maps = {mutbl_map: mutbl_map, copy_map: copy_map,
212-
last_uses: last_uses, impl_map: impl_map,
213-
method_map: method_map, vtable_map: vtable_map,
214-
spill_map: spill_map};
211+
let maps = {mutbl_map: mutbl_map, root_map: root_map,
212+
copy_map: copy_map, last_uses: last_uses,
213+
impl_map: impl_map, method_map: method_map,
214+
vtable_map: vtable_map, spill_map: spill_map};
215215

216216
let (llmod, link_meta) =
217217
time(time_passes, "translation",

src/rustc/middle/astencode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export decode_inlined_item;
4949
// Auxiliary maps of things to be encoded
5050
type maps = {
5151
mutbl_map: middle::borrowck::mutbl_map,
52+
root_map: middle::borrowck::root_map,
5253
copy_map: middle::alias::copy_map,
5354
last_uses: middle::last_use::last_uses,
5455
impl_map: middle::resolve::impl_map,

src/rustc/middle/borrowck.rs

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn check_crate(tcx: ty::ctxt,
2727
let bccx = @{tcx: tcx,
2828
method_map: method_map,
2929
msg_level: msg_level,
30-
root_map: int_hash(),
30+
root_map: root_map(),
3131
mutbl_map: int_hash()};
3232

3333
let req_loan_map = if msg_level > 0u {
@@ -53,7 +53,14 @@ type borrowck_ctxt = @{tcx: ty::ctxt,
5353
// a map mapping id's of expressions of task-local type (@T, []/@, etc) where
5454
// the box needs to be kept live to the id of the scope for which they must
5555
// stay live.
56-
type root_map = hashmap<ast::node_id, ast::node_id>;
56+
type root_map = hashmap<root_map_key, ast::node_id>;
57+
58+
// the keys to the root map combine the `id` of the expression with
59+
// the number of types that it is autodereferenced. So, for example,
60+
// if you have an expression `x.f` and x has type ~@T, we could add an
61+
// entry {id:x, derefs:0} to refer to `x` itself, `{id:x, derefs:1}`
62+
// to refer to the deref of the unique pointer, and so on.
63+
type root_map_key = {id: ast::node_id, derefs: uint};
5764

5865
// set of ids of local vars / formal arguments that are modified / moved.
5966
// this is used in trans for optimization purposes.
@@ -71,13 +78,13 @@ type bckerr = {cmt: cmt, code: bckerr_code};
7178
type bckres<T> = result<T, bckerr>;
7279

7380
enum categorization {
74-
cat_rvalue, // result of eval'ing some misc expr
75-
cat_special(special_kind), //
76-
cat_local(ast::node_id), // local variable
77-
cat_arg(ast::node_id), // formal argument
78-
cat_stack_upvar(cmt), // upvar in stack closure
79-
cat_deref(cmt, ptr_kind), // deref of a ptr
80-
cat_comp(cmt, comp_kind), // adjust to locate an internal component
81+
cat_rvalue, // result of eval'ing some misc expr
82+
cat_special(special_kind), //
83+
cat_local(ast::node_id), // local variable
84+
cat_arg(ast::node_id), // formal argument
85+
cat_stack_upvar(cmt), // upvar in stack closure
86+
cat_deref(cmt, uint, ptr_kind), // deref of a ptr
87+
cat_comp(cmt, comp_kind), // adjust to locate an internal component
8188
}
8289

8390
// different kinds of pointers:
@@ -156,6 +163,18 @@ fn save_and_restore<T:copy,U>(&t: T, f: fn() -> U) -> U {
156163
ret u;
157164
}
158165

166+
fn root_map() -> root_map {
167+
ret hashmap(root_map_key_hash, root_map_key_eq);
168+
169+
fn root_map_key_eq(k1: root_map_key, k2: root_map_key) -> bool {
170+
k1.id == k2.id && k1.derefs == k2.derefs
171+
}
172+
173+
fn root_map_key_hash(k: root_map_key) -> uint {
174+
(k.id << 4) as uint | k.derefs
175+
}
176+
}
177+
159178
// ----------------------------------------------------------------------
160179
// Gathering loans
161180
//
@@ -374,7 +393,7 @@ impl methods for gather_loan_ctxt {
374393

375394
ast::pat_box(subpat) | ast::pat_uniq(subpat) {
376395
// @p1, ~p1
377-
alt self.bccx.cat_deref(pat, cmt, true) {
396+
alt self.bccx.cat_deref(pat, cmt, 0u, true) {
378397
some(subcmt) { self.gather_pat(subcmt, subpat, alt_id); }
379398
none { tcx.sess.span_bug(pat.span, "Non derefable type"); }
380399
}
@@ -915,7 +934,7 @@ impl categorize_methods for borrowck_ctxt {
915934

916935
ty::ty_uniq(*) | ty::ty_box(*) | ty::ty_rptr(*) {
917936
let cmt = self.cat_expr(expr);
918-
self.cat_deref(expr, cmt, true).get()
937+
self.cat_deref(expr, cmt, 0u, true).get()
919938
}
920939

921940
_ {
@@ -943,7 +962,7 @@ impl categorize_methods for borrowck_ctxt {
943962
alt expr.node {
944963
ast::expr_unary(ast::deref, e_base) {
945964
let base_cmt = self.cat_expr(e_base);
946-
alt self.cat_deref(expr, base_cmt, true) {
965+
alt self.cat_deref(expr, base_cmt, 0u, true) {
947966
some(cmt) { ret cmt; }
948967
none {
949968
tcx.sess.span_bug(
@@ -955,7 +974,7 @@ impl categorize_methods for borrowck_ctxt {
955974
}
956975

957976
ast::expr_field(base, f_name, _) {
958-
let base_cmt = self.cat_autoderef(expr, base);
977+
let base_cmt = self.cat_autoderef(base);
959978
self.cat_field(expr, base_cmt, f_name, expr_ty)
960979
}
961980

@@ -1010,7 +1029,7 @@ impl categorize_methods for borrowck_ctxt {
10101029
mutbl: m, ty: f_ty}
10111030
}
10121031

1013-
fn cat_deref<N:ast_node>(node: N, base_cmt: cmt,
1032+
fn cat_deref<N:ast_node>(node: N, base_cmt: cmt, derefs: uint,
10141033
expl: bool) -> option<cmt> {
10151034
ty::deref(self.tcx, base_cmt.ty, expl).map { |mt|
10161035
alt deref_kind(self.tcx, base_cmt.ty) {
@@ -1027,7 +1046,7 @@ impl categorize_methods for borrowck_ctxt {
10271046
}
10281047
};
10291048
@{id:node.id(), span:node.span(),
1030-
cat:cat_deref(base_cmt, ptr), lp:lp,
1049+
cat:cat_deref(base_cmt, derefs, ptr), lp:lp,
10311050
mutbl:mt.mutbl, ty:mt.ty}
10321051
}
10331052

@@ -1041,7 +1060,7 @@ impl categorize_methods for borrowck_ctxt {
10411060
}
10421061
}
10431062

1044-
fn cat_autoderef(expr: @ast::expr, base: @ast::expr) -> cmt {
1063+
fn cat_autoderef(base: @ast::expr) -> cmt {
10451064
// Creates a string of implicit derefences so long as base is
10461065
// dereferencable. n.b., it is important that these dereferences are
10471066
// associated with the field/index that caused the autoderef (expr).
@@ -1050,16 +1069,18 @@ impl categorize_methods for borrowck_ctxt {
10501069
// Given something like base.f where base has type @m1 @m2 T, we want
10511070
// to yield the equivalent categories to (**base).f.
10521071
let mut cmt = self.cat_expr(base);
1072+
let mut ctr = 0u;
10531073
loop {
1054-
alt self.cat_deref(expr, cmt, false) {
1074+
ctr += 1u;
1075+
alt self.cat_deref(base, cmt, ctr, false) {
10551076
none { ret cmt; }
10561077
some(cmt1) { cmt = cmt1; }
10571078
}
10581079
}
10591080
}
10601081

10611082
fn cat_index(expr: @ast::expr, base: @ast::expr) -> cmt {
1062-
let base_cmt = self.cat_autoderef(expr, base);
1083+
let base_cmt = self.cat_autoderef(base);
10631084

10641085
let mt = alt ty::index(self.tcx, base_cmt.ty) {
10651086
some(mt) { mt }
@@ -1084,7 +1105,7 @@ impl categorize_methods for borrowck_ctxt {
10841105
// the head of this section
10851106
let deref_lp = base_cmt.lp.map { |lp| @lp_deref(lp, ptr) };
10861107
let deref_cmt = @{id:expr.id, span:expr.span,
1087-
cat:cat_deref(base_cmt, ptr), lp:deref_lp,
1108+
cat:cat_deref(base_cmt, 0u, ptr), lp:deref_lp,
10881109
mutbl:mt.mutbl, ty:mt.ty};
10891110
let comp = comp_index(base_cmt.ty);
10901111
let index_lp = deref_lp.map { |lp| @lp_comp(lp, comp) };
@@ -1211,8 +1232,9 @@ impl categorize_methods for borrowck_ctxt {
12111232
cat_rvalue { "rvalue" }
12121233
cat_local(node_id) { #fmt["local(%d)", node_id] }
12131234
cat_arg(node_id) { #fmt["arg(%d)", node_id] }
1214-
cat_deref(cmt, ptr) {
1215-
#fmt["%s->(%s)", self.cat_to_repr(cmt.cat), self.ptr_sigil(ptr)]
1235+
cat_deref(cmt, derefs, ptr) {
1236+
#fmt["%s->(%s, %u)", self.cat_to_repr(cmt.cat),
1237+
self.ptr_sigil(ptr), derefs]
12161238
}
12171239
cat_comp(cmt, comp) {
12181240
#fmt["%s.%s", self.cat_to_repr(cmt.cat), self.comp_to_repr(comp)]
@@ -1285,7 +1307,7 @@ impl categorize_methods for borrowck_ctxt {
12851307
cat_rvalue { "non-lvalue" }
12861308
cat_local(_) { mut_str + " local variable" }
12871309
cat_arg(_) { mut_str + " argument" }
1288-
cat_deref(_, _) { "dereference of " + mut_str + " pointer" }
1310+
cat_deref(*) { "dereference of " + mut_str + " pointer" }
12891311
cat_stack_upvar(_) { mut_str + " upvar" }
12901312
cat_comp(_, comp_field(_)) { mut_str + " field" }
12911313
cat_comp(_, comp_tuple) { "tuple content" }
@@ -1446,26 +1468,31 @@ impl preserve_methods for preserve_ctxt {
14461468
cat_comp(cmt1, comp_variant) {
14471469
self.require_imm(cmt, cmt1, err_mut_variant)
14481470
}
1449-
cat_deref(cmt1, uniq_ptr) {
1471+
cat_deref(cmt1, _, uniq_ptr) {
14501472
self.require_imm(cmt, cmt1, err_mut_uniq)
14511473
}
1452-
cat_deref(_, region_ptr) {
1474+
cat_deref(_, _, region_ptr) {
14531475
// References are always "stable" by induction (when the
14541476
// reference of type &MT was created, the memory must have
14551477
// been stable)
14561478
ok(())
14571479
}
1458-
cat_deref(_, unsafe_ptr) {
1480+
cat_deref(_, _, unsafe_ptr) {
14591481
// Unsafe pointers are the user's problem
14601482
ok(())
14611483
}
1462-
cat_deref(_, gc_ptr) {
1484+
cat_deref(_, derefs, gc_ptr) {
14631485
// GC'd pointers of type @MT: always stable because we can inc
14641486
// the ref count or keep a GC root as necessary. We need to
14651487
// insert this id into the root_map, however.
14661488
alt self.opt_scope_id {
14671489
some(scope_id) {
1468-
self.bccx.root_map.insert(cmt.id, scope_id);
1490+
#debug["Inserting root map entry for %s: \
1491+
node %d:%u -> scope %d",
1492+
self.bccx.cmt_to_repr(cmt), cmt.id,
1493+
derefs, scope_id];
1494+
let rk = {id: cmt.id, derefs: derefs};
1495+
self.bccx.root_map.insert(rk, scope_id);
14691496
ok(())
14701497
}
14711498
none {
@@ -1562,7 +1589,7 @@ impl loan_methods for loan_ctxt {
15621589
}
15631590
}
15641591
cat_comp(cmt1, comp_variant) |
1565-
cat_deref(cmt1, uniq_ptr) {
1592+
cat_deref(cmt1, _, uniq_ptr) {
15661593
// Variant components: the base must be immutable, because
15671594
// if it is overwritten, the types of the embedded data
15681595
// could change.
@@ -1573,9 +1600,9 @@ impl loan_methods for loan_ctxt {
15731600
self.ok_with_loan_of(cmt, req_mutbl)
15741601
}
15751602
}
1576-
cat_deref(cmt1, unsafe_ptr) |
1577-
cat_deref(cmt1, gc_ptr) |
1578-
cat_deref(cmt1, region_ptr) {
1603+
cat_deref(cmt1, _, unsafe_ptr) |
1604+
cat_deref(cmt1, _, gc_ptr) |
1605+
cat_deref(cmt1, _, region_ptr) {
15791606
// Aliased data is simply not lendable.
15801607
self.bccx.tcx.sess.span_bug(
15811608
cmt.span,

0 commit comments

Comments
 (0)