diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index bb92043b1ea..9c2194c74f4 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -25,6 +25,7 @@ use middle::dataflow::DataFlowContext; use middle::dataflow::BitwiseOperator; use middle::dataflow::DataFlowOperator; use euv = middle::expr_use_visitor; +use mc = middle::mem_categorization; use middle::ty; use syntax::ast; use syntax::ast_util; @@ -160,6 +161,22 @@ pub struct AssignDataFlowOperator; pub type AssignDataFlow<'a> = DataFlowContext<'a, AssignDataFlowOperator>; +fn loan_path_is_precise(loan_path: &LoanPath) -> bool { + match *loan_path { + LpVar(_) => { + true + } + LpExtend(_, _, LpInterior(mc::InteriorElement(_))) => { + // Paths involving element accesses do not refer to a unique + // location, as there is no accurate tracking of the indices. + false + } + LpExtend(ref lp_base, _, _) => { + loan_path_is_precise(&**lp_base) + } + } +} + impl MoveData { pub fn new() -> MoveData { MoveData { @@ -500,10 +517,17 @@ impl MoveData { path: MovePathIndex, kill_id: ast::NodeId, dfcx_moves: &mut MoveDataFlow) { - self.each_applicable_move(path, |move_index| { - dfcx_moves.add_kill(kill_id, move_index.get()); - true - }); + // We can only perform kills for paths that refer to a unique location, + // since otherwise we may kill a move from one location with an + // assignment referring to another location. + + let loan_path = self.path_loan_path(path); + if loan_path_is_precise(&*loan_path) { + self.each_applicable_move(path, |move_index| { + dfcx_moves.add_kill(kill_id, move_index.get()); + true + }); + } } } diff --git a/src/test/compile-fail/borrowck-array-double-move.rs b/src/test/compile-fail/borrowck-array-double-move.rs new file mode 100644 index 00000000000..c7fb646f585 --- /dev/null +++ b/src/test/compile-fail/borrowck-array-double-move.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() { + let mut a = [box 0, box 1]; + drop(a[0]); + a[1] = box 2; + drop(a[0]); //~ ERROR use of moved value: `a[..]` +} + +fn main() { + f(); +} +