Skip to content

Commit 287f163

Browse files
committed
Issue #2657: track mutability of bindings, also prevent move from bindings
1 parent c3d384b commit 287f163

File tree

8 files changed

+50
-8
lines changed

8 files changed

+50
-8
lines changed

src/libsyntax/parse/lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ fn tt_next_token(&&r: tt_reader) -> {tok: token::token, sp: span} {
154154
ret ret_val;
155155
}
156156
tt_frame_up(option::some(tt_f)) {
157-
r.cur <- tt_f;
157+
r.cur = tt_f;
158158
/* the above `if` would need to be a `while` if we didn't know
159159
that the last thing in a `tt_delim` is always a `tt_flat` */
160160
r.cur.idx += 1u;

src/rustc/middle/borrowck.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ fn check_crate(tcx: ty::ctxt,
175175
let bccx = @{tcx: tcx,
176176
method_map: method_map,
177177
last_use_map: last_use_map,
178+
binding_map: int_hash(),
178179
root_map: root_map(),
179180
mutbl_map: int_hash()};
180181

@@ -189,6 +190,7 @@ fn check_crate(tcx: ty::ctxt,
189190
type borrowck_ctxt = @{tcx: ty::ctxt,
190191
method_map: typeck::method_map,
191192
last_use_map: liveness::last_use_map,
193+
binding_map: binding_map,
192194
root_map: root_map,
193195
mutbl_map: mutbl_map};
194196

@@ -208,6 +210,10 @@ type root_map_key = {id: ast::node_id, derefs: uint};
208210
// this is used in trans for optimization purposes.
209211
type mutbl_map = std::map::hashmap<ast::node_id, ()>;
210212

213+
// maps from each binding's id to the mutability of the location it
214+
// points at. See gather_loan.rs for more detail (search for binding_map)
215+
type binding_map = std::map::hashmap<ast::node_id, ast::mutability>;
216+
211217
// Errors that can occur"]
212218
enum bckerr_code {
213219
err_mut_uniq,
@@ -228,6 +234,7 @@ enum categorization {
228234
cat_rvalue, // result of eval'ing some misc expr
229235
cat_special(special_kind), //
230236
cat_local(ast::node_id), // local variable
237+
cat_binding(ast::node_id), // pattern binding
231238
cat_arg(ast::node_id), // formal argument
232239
cat_stack_upvar(cmt), // upvar in stack closure
233240
cat_deref(cmt, uint, ptr_kind), // deref of a ptr
@@ -381,6 +388,7 @@ impl to_str_methods for borrowck_ctxt {
381388
cat_stack_upvar(_) { "stack-upvar" }
382389
cat_rvalue { "rvalue" }
383390
cat_local(node_id) { #fmt["local(%d)", node_id] }
391+
cat_binding(node_id) { #fmt["binding(%d)", node_id] }
384392
cat_arg(node_id) { #fmt["arg(%d)", node_id] }
385393
cat_deref(cmt, derefs, ptr) {
386394
#fmt["%s->(%s, %u)", self.cat_to_repr(cmt.cat),
@@ -466,6 +474,7 @@ impl to_str_methods for borrowck_ctxt {
466474
cat_special(sk_heap_upvar) { "variable declared in an outer block" }
467475
cat_rvalue { "non-lvalue" }
468476
cat_local(_) { mut_str + " local variable" }
477+
cat_binding(_) { "pattern binding" }
469478
cat_arg(_) { "argument" }
470479
cat_deref(_, _, pk) { #fmt["dereference of %s %s pointer",
471480
mut_str, self.pk_to_sigil(pk)] }

src/rustc/middle/borrowck/categorization.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,16 @@ impl public_methods for borrowck_ctxt {
265265
mutbl:m, ty:expr_ty}
266266
}
267267

268-
ast::def_binding(vid) {
269-
// no difference between a binding and any other local variable
270-
// from out point of view, except that they are always immutable
268+
ast::def_binding(pid) {
269+
// bindings are "special" since they are implicit pointers.
270+
271+
// lookup the mutability for this binding that we found in
272+
// gather_loans when we categorized it
273+
let mutbl = self.binding_map.get(pid);
274+
271275
@{id:id, span:span,
272-
cat:cat_local(vid), lp:some(@lp_local(vid)),
273-
mutbl:m_imm, ty:expr_ty}
276+
cat:cat_binding(pid), lp:none,
277+
mutbl:mutbl, ty:expr_ty}
274278
}
275279
}
276280
}

src/rustc/middle/borrowck/gather_loans.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,16 @@ impl methods for gather_loan_ctxt {
364364
// cat_discr in the method preserve():
365365
let cmt1 = self.bccx.cat_discr(cmt, alt_id);
366366
let arm_scope = ty::re_scope(arm_id);
367+
368+
// Remember the mutability of the location that this
369+
// binding refers to. This will be used later when
370+
// categorizing the binding. This is a bit of a hack that
371+
// would be better fixed by #2329; in that case we could
372+
// allow the user to specify if they want an imm, const,
373+
// or mut binding, or else just reflect the mutability
374+
// through the type of the region pointer.
375+
self.bccx.binding_map.insert(pat.id, cmt1.mutbl);
376+
367377
self.guarantee_valid(cmt1, m_const, arm_scope);
368378

369379
for o_pat.each { |p|

src/rustc/middle/borrowck/loan.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl loan_methods for loan_ctxt {
4343
}
4444

4545
alt cmt.cat {
46-
cat_rvalue | cat_special(_) {
46+
cat_binding(_) | cat_rvalue | cat_special(_) {
4747
// should never be loanable
4848
self.bccx.tcx.sess.span_bug(
4949
cmt.span,

src/rustc/middle/borrowck/preserve.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ impl public_methods for borrowck_ctxt {
2929
}
3030
ok(())
3131
}
32+
cat_binding(_) {
33+
// Bindings are these kind of weird implicit pointers (cc
34+
// #2329). We require (in gather_loans) that they be
35+
// rooted in an immutable location.
36+
ok(())
37+
}
3238
cat_arg(_) {
3339
// This can happen as not all args are lendable (e.g., &&
3440
// modes). In that case, the caller guarantees stability.

src/rustc/middle/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3335,7 +3335,7 @@ fn need_invoke(bcx: block) -> bool {
33353335
loop {
33363336
alt cur.kind {
33373337
block_scope(inf) {
3338-
for inf.cleanups.each {|cleanup|
3338+
for vec::each(inf.cleanups) {|cleanup|
33393339
alt cleanup {
33403340
clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) {
33413341
if cleanup_type == normal_exit_and_unwind {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn impure(_v: [int]) {
2+
}
3+
4+
fn main() {
5+
let x = {mut f: [3]};
6+
7+
alt x {
8+
{f: v} => {
9+
impure(v); //! ERROR illegal borrow unless pure: unique value in aliasable, mutable location
10+
//!^ NOTE impure due to access to impure function
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)