From 22a14dd700338ed26f78143dfad4325566a3f4ed Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 9 Aug 2012 14:18:43 -0700 Subject: [PATCH] Enforce a stricter notion of purity when borrowing. Fixes #3162. --- src/rustc/middle/borrowck/check_loans.rs | 26 +++++++++++++++++-- ...k-imm-ref-to-mut-rec-field-issue-3162-b.rs | 12 +++++++++ ...wck-imm-ref-to-mut-rec-field-issue-3162.rs | 12 +++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-b.rs create mode 100644 src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162.rs diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index 4c596a343544..301c78aa1094 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -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))); } } } diff --git a/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-b.rs b/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-b.rs new file mode 100644 index 000000000000..3c0a53130b1d --- /dev/null +++ b/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-b.rs @@ -0,0 +1,12 @@ +fn each(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); + } +} diff --git a/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162.rs b/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162.rs new file mode 100644 index 000000000000..fa31ca4340be --- /dev/null +++ b/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162.rs @@ -0,0 +1,12 @@ +fn each(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); + } +}