Skip to content

Commit

Permalink
More complete fix to rust-lang#3162 (borrowck bug related to access t…
Browse files Browse the repository at this point in the history
…o rec fields)
  • Loading branch information
nikomatsakis authored and catamorphism committed Aug 28, 2012
1 parent 1359439 commit 16727d9
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 39 deletions.
10 changes: 4 additions & 6 deletions src/libcore/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,12 +851,10 @@ fn each_ancestor(list: &mut AncestorList,
do with_parent_tg(&mut nobe.parent_group) |tg_opt| {
// Decide whether this group is dead. Note that the
// group being *dead* is disjoint from it *failing*.
match *tg_opt {
some(ref tg) => {
nobe_is_dead = taskgroup_is_dead(tg);
},
none => { }
}
nobe_is_dead = match *tg_opt {
some(ref tg) => taskgroup_is_dead(tg),
none => nobe_is_dead
};
// Call iterator block. (If the group is dead, it's
// safe to skip it. This will leave our *rust_task
// hanging around in the group even after it's freed,
Expand Down
19 changes: 19 additions & 0 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export swap;
export reverse;
export reversed;
export iter, iter_between, each, eachi, reach, reachi;
export each_mut, each_const;
export iter2;
export iteri;
export riter;
Expand Down Expand Up @@ -1174,6 +1175,24 @@ pure fn each<T>(v: &[T], f: fn(T) -> bool) {
}
}

/// Like `each()`, but for the case where you have
/// a vector with mutable contents and you would like
/// to mutate the contents as you iterate.
#[inline(always)]
pure fn each_mut<T>(v: &[mut T], f: fn(elem: &mut T) -> bool) {
do vec::as_mut_buf(v) |p, n| {
let mut n = n;
let mut p = p;
while n > 0u {
unsafe {
if !f(&mut *p) { break; }
p = ptr::mut_offset(p, 1u);
}
n -= 1u;
}
}
}

/**
* Iterates over a vector's elements and indices
*
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/sha1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ fn sha1() -> sha1 {
fn mk_result(st: sha1state) -> ~[u8] {
if !st.computed { pad_msg(st); st.computed = true; }
let mut rs: ~[u8] = ~[];
for vec::each(st.h) |hpart| {
for vec::each_mut(st.h) |ptr_hpart| {
let hpart = *ptr_hpart;
let a = (hpart >> 24u32 & 0xFFu32) as u8;
let b = (hpart >> 16u32 & 0xFFu32) as u8;
let c = (hpart >> 8u32 & 0xFFu32) as u8;
Expand Down
9 changes: 5 additions & 4 deletions src/libsyntax/ext/simplext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,10 @@ fn transcribe(cx: ext_ctxt, b: bindings, body: @expr) -> @expr {


/* helper: descend into a matcher */
fn follow(m: arb_depth<matchable>, idx_path: @mut ~[uint]) ->
pure fn follow(m: arb_depth<matchable>, idx_path: &[uint]) ->
arb_depth<matchable> {
let mut res: arb_depth<matchable> = m;
for vec::each(*idx_path) |idx| {
for vec::each(idx_path) |idx| {
res = match res {
leaf(_) => return res,/* end of the line */
seq(new_ms, _) => new_ms[idx]
Expand All @@ -222,7 +222,7 @@ fn follow_for_trans(cx: ext_ctxt, mmaybe: option<arb_depth<matchable>>,
match mmaybe {
none => return none,
some(m) => {
return match follow(m, idx_path) {
return match follow(m, *idx_path) {
seq(_, sp) => {
cx.span_fatal(sp,
~"syntax matched under ... but not " +
Expand Down Expand Up @@ -274,7 +274,8 @@ fn transcribe_exprs(cx: ext_ctxt, b: bindings, idx_path: @mut ~[uint],
/* we need to walk over all the free vars in lockstep, except for
the leaves, which are just duplicated */
do free_vars(b, repeat_me) |fv| {
let cur_pos = follow(b.get(fv), idx_path);
let fv_depth = b.get(fv);
let cur_pos = follow(fv_depth, *idx_path);
match cur_pos {
leaf(_) => (),
seq(ms, _) => {
Expand Down
15 changes: 4 additions & 11 deletions src/libsyntax/parse/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,12 @@ impl parser: parser_common {

fn eat_keyword(word: ~str) -> bool {
self.require_keyword(word);

let mut bump = false;
let val = match self.token {
token::IDENT(sid, false) => {
if word == *self.id_to_str(sid) {
bump = true;
true
} else { false }
}
let is_kw = match self.token {
token::IDENT(sid, false) => (word == *self.id_to_str(sid)),
_ => false
};
if bump { self.bump() }
val
if is_kw { self.bump() }
is_kw
}

fn expect_keyword(word: ~str) {
Expand Down
15 changes: 2 additions & 13 deletions src/rustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,19 +326,8 @@ impl check_loan_ctxt {
// even to data owned by the current stack frame. This is
// because that aliasable data might have been located on
// the current stack frame, we don't know.
match cmt.lp {
some(@lp_local(*)) | some(@lp_arg(*)) => {
// it's ok to mutate a local variable, as it is either
// lent our or not. The problem arises when you have
// some subcomponent that might have been lent out
// through an alias on the condition that you ensure
// purity.
}
none | some(@lp_comp(*)) | some(@lp_deref(*)) => {
self.report_purity_error(
pc, ex.span, at.ing_form(self.bccx.cmt_to_str(cmt)));
}
}
self.report_purity_error(
pc, ex.span, at.ing_form(self.bccx.cmt_to_str(cmt)));
}
some(pc_pure_fn) => {
if cmt.lp.is_none() {
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/resolve3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2065,7 +2065,7 @@ struct Resolver {
str_of(name)));
return Failed;
}
ModuleDef(module_) => {
ModuleDef(copy module_) => {
search_module = module_;
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/rustc/middle/trans/type_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,13 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
}

fn type_needs(cx: ctx, use: uint, ty: ty::t) {
let mut done = true;
// Optimization -- don't descend type if all params already have this use
for vec::each(cx.uses) |u| { if u & use != use { done = false } }
if !done { type_needs_inner(cx, use, ty, @nil); }
for vec::each_mut(cx.uses) |u| {
if *u & use != use {
type_needs_inner(cx, use, ty, @nil);
return;
}
}
}

fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
let mut _a = 3;
let _b = &mut _a;
{
let _c = &*_b; //~ ERROR illegal borrow unless pure
_a = 4; //~ NOTE impure due to assigning to mutable local variable
}
}

0 comments on commit 16727d9

Please sign in to comment.