Enforce a stricter notion of purity when borrowing. Fixes #3162.
This commit is contained in:
parent
be2e4ef624
commit
22a14dd700
3 changed files with 48 additions and 2 deletions
|
|
@ -322,10 +322,32 @@ impl check_loan_ctxt {
|
|||
// is not visible from the outside
|
||||
match self.purity(ex.id) {
|
||||
none => (),
|
||||
some(pc) => {
|
||||
if cmt.lp.is_none() {
|
||||
some(pc @ pc_cmt(_)) => {
|
||||
// Subtle: Issue #3162. If we are enforcing purity
|
||||
// because there is a reference to aliasable, mutable data
|
||||
// that we require to be immutable, we can't allow writes
|
||||
// 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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
some(pc_pure_fn) => {
|
||||
if cmt.lp.is_none() {
|
||||
self.report_purity_error(
|
||||
pc_pure_fn, ex.span,
|
||||
at.ing_form(self.bccx.cmt_to_str(cmt)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
fn each<T>(x: &[T], op: fn(elem: &T) -> bool) {
|
||||
uint::range(0, x.len(), |i| op(&x[i]));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = [{mut a: 0}];
|
||||
for each(x) |y| {
|
||||
let z = &y.a; //~ ERROR illegal borrow unless pure
|
||||
x[0].a = 10; //~ NOTE impure due to assigning to mutable field
|
||||
log(error, z);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
fn each<T>(x: &[T], op: fn(elem: &T) -> bool) {
|
||||
uint::range(0, x.len(), |i| op(&x[i]));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = ~[{mut a: 0}];
|
||||
for each(x) |y| {
|
||||
let z = &y.a; //~ ERROR illegal borrow unless pure
|
||||
x[0].a = 10; //~ NOTE impure due to assigning to mutable field
|
||||
log(error, z);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue