diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c907c97d6d3..1e8a6792963 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -338,15 +338,10 @@ fn visit_statement_entry( match stmt.kind { StatementKind::Assign(ref lhs, ref rhs) => { - // NOTE: NLL RFC calls for *shallow* write; using Deep - // for short-term compat w/ AST-borrowck. Also, switch - // to shallow requires to dataflow: "if this is an - // assignment `place = `, then any loan for some - // path P of which `place` is a prefix is killed." self.mutate_place( ContextKind::AssignLhs.new(location), (lhs, span), - Deep, + Shallow(None), JustWrite, flow_state, ); diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 8083c1debb8..c39ae10371c 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::region; @@ -362,6 +363,14 @@ fn statement_effect_on_borrows(&self, } mir::StatementKind::Assign(ref lhs, ref rhs) => { + // Make sure there are no remaining borrows for variables + // that are assigned over. + if let Place::Local(ref local) = *lhs { + // FIXME: Handle the case in which we're assigning over + // a projection (`foo.bar`). + self.kill_borrows_on_local(sets, local, is_activations); + } + // NOTE: if/when the Assign case is revised to inspect // the assigned_place here, make sure to also // re-consider the current implementations of the @@ -404,16 +413,7 @@ fn statement_effect_on_borrows(&self, mir::StatementKind::StorageDead(local) => { // Make sure there are no remaining borrows for locals that // are gone out of scope. - // - // FIXME: expand this to variables that are assigned over. - if let Some(borrow_indexes) = self.local_map.get(&local) { - sets.kill_all(borrow_indexes.iter() - .map(|b| ReserveOrActivateIndex::reserved(*b))); - if is_activations { - sets.kill_all(borrow_indexes.iter() - .map(|b| ReserveOrActivateIndex::active(*b))); - } - } + self.kill_borrows_on_local(sets, &local, is_activations) } mir::StatementKind::InlineAsm { .. } | @@ -425,6 +425,21 @@ fn statement_effect_on_borrows(&self, } } + fn kill_borrows_on_local(&self, + sets: &mut BlockSets, + local: &rustc::mir::Local, + is_activations: bool) + { + if let Some(borrow_indexes) = self.local_map.get(local) { + sets.kill_all(borrow_indexes.iter() + .map(|b| ReserveOrActivateIndex::reserved(*b))); + if is_activations { + sets.kill_all(borrow_indexes.iter() + .map(|b| ReserveOrActivateIndex::active(*b))); + } + } + } + /// Models terminator effect in Reservations and ActiveBorrows /// flow analyses; `is activations` tells us if we are in the /// latter case. diff --git a/src/test/compile-fail/issue-25579.rs b/src/test/compile-fail/issue-25579.rs index 5f5a58ed759..71c1d63cf5a 100644 --- a/src/test/compile-fail/issue-25579.rs +++ b/src/test/compile-fail/issue-25579.rs @@ -11,21 +11,22 @@ // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir +#![feature(rustc_attrs)] + enum Sexpression { Num(()), Cons(&'static mut Sexpression) } -fn causes_ice(mut l: &mut Sexpression) { +fn causes_error_in_ast(mut l: &mut Sexpression) { loop { match l { &mut Sexpression::Num(ref mut n) => {}, &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499] - //[mir]~^ ERROR [E0499] l = &mut **expr; //[ast]~ ERROR [E0506] - //[mir]~^ ERROR [E0506] } }} } -fn main() { +#[rustc_error] +fn main() { //[mir]~ ERROR compilation successful } diff --git a/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs b/src/test/run-pass/borrowck/borrowck-nll-iterating-and-updating.rs similarity index 56% rename from src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs rename to src/test/run-pass/borrowck/borrowck-nll-iterating-and-updating.rs index 93c774e8996..043f1215ea5 100644 --- a/src/test/compile-fail/nll/where_clauses_in_repeat_rvalue.rs +++ b/src/test/run-pass/borrowck/borrowck-nll-iterating-and-updating.rs @@ -10,30 +10,25 @@ // compile-flags: -Z borrowck=mir -Z nll -#![allow(warnings)] +// This example comes from the NLL RFC. -struct Foo { - t: T, +struct List { + value: T, + next: Option>>, } -impl Copy for Foo {} -impl Clone for Foo { - fn clone(&self) -> Self { - *self +fn to_refs(list: &mut List) -> Vec<&mut T> { + let mut list = list; + let mut result = vec![]; + loop { + result.push(&mut list.value); + if let Some(n) = list.next.as_mut() { + list = n; + } else { + return result; + } } } fn main() { - let mut x = 22; - - { - let p = &x; - //~^ ERROR `x` does not live long enough - let w = Foo { t: p }; - - let v = [w; 22]; - } - - x += 1; - //~^ ERROR cannot assign to `x` because it is borrowed [E0506] }