diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 5de23b42f5c..6a29a9a75b8 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -1564,7 +1564,8 @@ fn remove(node: &mut Option>>, save.level -= 1; if right_level > save.level { - for x in save.right.mut_iter() { x.level = save.level } + let save_level = save.level; + for x in save.right.mut_iter() { x.level = save_level } } skew(save); diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index cd011b0e013..ec7ed919177 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -783,7 +783,7 @@ fn insert(count: &mut uint, child: &mut Child, key: uint, value: T, *child = External(key, value); return None; } - Internal(ref mut x) => { + Internal(box ref mut x) => { return insert(&mut x.count, &mut x.children[chunk(key, idx)], key, value, idx + 1); } External(stored_key, ref mut stored_value) if stored_key == key => { @@ -799,11 +799,17 @@ fn insert(count: &mut uint, child: &mut Child, key: uint, value: T, match mem::replace(child, Nothing) { External(stored_key, stored_value) => { let mut new = box TrieNode::new(); - insert(&mut new.count, - &mut new.children[chunk(stored_key, idx)], - stored_key, stored_value, idx + 1); - let ret = insert(&mut new.count, &mut new.children[chunk(key, idx)], - key, value, idx + 1); + + let ret = { + let new_interior = &mut *new; + insert(&mut new_interior.count, + &mut new_interior.children[chunk(stored_key, idx)], + stored_key, stored_value, idx + 1); + insert(&mut new_interior.count, + &mut new_interior.children[chunk(key, idx)], + key, value, idx + 1) + }; + *child = Internal(new); return ret; } @@ -821,7 +827,7 @@ fn remove(count: &mut uint, child: &mut Child, key: uint, } } External(..) => (None, false), - Internal(ref mut x) => { + Internal(box ref mut x) => { let ret = remove(&mut x.count, &mut x.children[chunk(key, idx)], key, idx + 1); (ret, x.count == 0) diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index b570cb43f16..7dec42538cf 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -28,6 +28,57 @@ use util::ppaux::Repr; use std::rc::Rc; +// FIXME (#16118): These functions are intended to allow the borrow checker to +// be less precise in its handling of Box while still allowing moves out of a +// Box. They should be removed when OwnedPtr is removed from LoanPath. + +fn owned_ptr_base_path<'a>(loan_path: &'a LoanPath) -> &'a LoanPath { + //! Returns the base of the leftmost dereference of an OwnedPtr in + //! `loan_path`. If there is no dereference of an OwnedPtr in `loan_path`, + //! then it just returns `loan_path` itself. + + return match owned_ptr_base_path_helper(loan_path) { + Some(new_loan_path) => new_loan_path, + None => loan_path.clone() + }; + + fn owned_ptr_base_path_helper<'a>(loan_path: &'a LoanPath) -> Option<&'a LoanPath> { + match *loan_path { + LpVar(_) | LpUpvar(_) => None, + LpExtend(ref lp_base, _, LpDeref(mc::OwnedPtr)) => { + match owned_ptr_base_path_helper(&**lp_base) { + v @ Some(_) => v, + None => Some(&**lp_base) + } + } + LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(&**lp_base) + } + } +} + +fn owned_ptr_base_path_rc(loan_path: &Rc) -> Rc { + //! The equivalent of `owned_ptr_base_path` for an &Rc rather than + //! a &LoanPath. + + return match owned_ptr_base_path_helper(loan_path) { + Some(new_loan_path) => new_loan_path, + None => loan_path.clone() + }; + + fn owned_ptr_base_path_helper(loan_path: &Rc) -> Option> { + match **loan_path { + LpVar(_) | LpUpvar(_) => None, + LpExtend(ref lp_base, _, LpDeref(mc::OwnedPtr)) => { + match owned_ptr_base_path_helper(lp_base) { + v @ Some(_) => v, + None => Some(lp_base.clone()) + } + } + LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(lp_base) + } + } +} + struct CheckLoanCtxt<'a> { bccx: &'a BorrowckCtxt<'a>, dfcx_loans: &'a LoanDataFlow<'a>, @@ -210,6 +261,7 @@ impl<'a> CheckLoanCtxt<'a> { // let x = &mut a.b.c; // Restricts a, a.b, and a.b.c // let y = a; // Conflicts with restriction + let loan_path = owned_ptr_base_path(loan_path); let cont = self.each_in_scope_loan(scope_id, |loan| { let mut ret = true; for restr_path in loan.restricted_paths.iter() { @@ -344,8 +396,9 @@ impl<'a> CheckLoanCtxt<'a> { return true; } + let loan2_base_path = owned_ptr_base_path_rc(&loan2.loan_path); for restr_path in loan1.restricted_paths.iter() { - if *restr_path != loan2.loan_path { continue; } + if *restr_path != loan2_base_path { continue; } let old_pronoun = if new_loan.loan_path == old_loan.loan_path { "it".to_string() @@ -597,7 +650,8 @@ impl<'a> CheckLoanCtxt<'a> { debug!("check_if_path_is_moved(id={:?}, use_kind={:?}, lp={})", id, use_kind, lp.repr(self.bccx.tcx)); - self.move_data.each_move_of(id, lp, |move, moved_lp| { + let base_lp = owned_ptr_base_path_rc(lp); + self.move_data.each_move_of(id, &base_lp, |move, moved_lp| { self.bccx.report_use_of_moved_value( span, use_kind, diff --git a/src/libstd/collections/lru_cache.rs b/src/libstd/collections/lru_cache.rs index 45e971a675f..32a16053fff 100644 --- a/src/libstd/collections/lru_cache.rs +++ b/src/libstd/collections/lru_cache.rs @@ -331,7 +331,8 @@ impl Drop for LruCache { unsafe { let node: Box> = mem::transmute(self.head); // Prevent compiler from trying to drop the un-initialized field in the sigil node. - let box LruEntry { key: k, value: v, .. } = node; + let box internal_node = node; + let LruEntry { next: _, prev: _, key: k, value: v } = internal_node; mem::forget(k); mem::forget(v); } diff --git a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs b/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs index c7695e0ff5f..208f58f6b54 100644 --- a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs +++ b/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -52,7 +52,7 @@ fn borrow_same_field_twice_imm_imm() { fn borrow_both_fields_mut() { let mut foo = make_foo(); let bar1 = &mut foo.bar1; - let _bar2 = &mut foo.bar2; + let _bar2 = &mut foo.bar2; //~ ERROR cannot borrow *bar1; } @@ -60,6 +60,7 @@ fn borrow_both_mut_pattern() { let mut foo = make_foo(); match *foo { Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => {} + //~^ ERROR cannot borrow } } @@ -120,7 +121,7 @@ fn borrow_imm_and_base_imm() { fn borrow_mut_and_imm() { let mut foo = make_foo(); let bar1 = &mut foo.bar1; - let _foo1 = &foo.bar2; + let _foo1 = &foo.bar2; //~ ERROR cannot borrow *bar1; } @@ -133,7 +134,7 @@ fn borrow_mut_from_imm() { fn borrow_long_path_both_mut() { let mut foo = make_foo(); let bar1 = &mut foo.bar1.int1; - let foo1 = &mut foo.bar2.int2; + let foo1 = &mut foo.bar2.int2; //~ ERROR cannot borrow *bar1; *foo1; } diff --git a/src/test/compile-fail/borrowck-box-insensitivity.rs b/src/test/compile-fail/borrowck-box-insensitivity.rs new file mode 100644 index 00000000000..c9b384e0b00 --- /dev/null +++ b/src/test/compile-fail/borrowck-box-insensitivity.rs @@ -0,0 +1,150 @@ +// 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. + +struct A { + x: Box, + y: int, +} + +struct B { + x: Box, + y: Box, +} + +struct C { + x: Box, + y: int, +} + +struct D { + x: Box, + y: Box, +} + +fn copy_after_move() { + let a = box A { x: box 0, y: 1 }; + let _x = a.x; + let _y = a.y; //~ ERROR use of partially moved +} + +fn move_after_move() { + let a = box B { x: box 0, y: box 1 }; + let _x = a.x; + let _y = a.y; //~ ERROR use of partially moved +} + +fn borrow_after_move() { + let a = box A { x: box 0, y: 1 }; + let _x = a.x; + let _y = &a.y; //~ ERROR use of partially moved +} + +fn move_after_borrow() { + let a = box B { x: box 0, y: box 1 }; + let _x = &a.x; + let _y = a.y; //~ ERROR cannot move +} + +fn copy_after_mut_borrow() { + let mut a = box A { x: box 0, y: 1 }; + let _x = &mut a.x; + let _y = a.y; //~ ERROR cannot use +} + +fn move_after_mut_borrow() { + let mut a = box B { x: box 0, y: box 1 }; + let _x = &mut a.x; + let _y = a.y; //~ ERROR cannot move +} + +fn borrow_after_mut_borrow() { + let mut a = box A { x: box 0, y: 1 }; + let _x = &mut a.x; + let _y = &a.y; //~ ERROR cannot borrow +} + +fn mut_borrow_after_borrow() { + let mut a = box A { x: box 0, y: 1 }; + let _x = &a.x; + let _y = &mut a.y; //~ ERROR cannot borrow +} + +fn copy_after_move_nested() { + let a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let _x = a.x.x; + let _y = a.y; //~ ERROR use of partially moved +} + +fn move_after_move_nested() { + let a = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let _x = a.x.x; + let _y = a.y; //~ ERROR use of partially moved +} + +fn borrow_after_move_nested() { + let a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let _x = a.x.x; + let _y = &a.y; //~ ERROR use of partially moved +} + +fn move_after_borrow_nested() { + let a = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let _x = &a.x.x; + let _y = a.y; //~ ERROR cannot move +} + +fn copy_after_mut_borrow_nested() { + let mut a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let _x = &mut a.x.x; + let _y = a.y; //~ ERROR cannot use +} + +fn move_after_mut_borrow_nested() { + let mut a = box D { x: box A { x: box 0, y: 1 }, y: box 2 }; + let _x = &mut a.x.x; + let _y = a.y; //~ ERROR cannot move +} + +fn borrow_after_mut_borrow_nested() { + let mut a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let _x = &mut a.x.x; + let _y = &a.y; //~ ERROR cannot borrow +} + +fn mut_borrow_after_borrow_nested() { + let mut a = box C { x: box A { x: box 0, y: 1 }, y: 2 }; + let _x = &a.x.x; + let _y = &mut a.y; //~ ERROR cannot borrow +} + +fn main() { + copy_after_move(); + move_after_move(); + borrow_after_move(); + + move_after_borrow(); + + copy_after_mut_borrow(); + move_after_mut_borrow(); + borrow_after_mut_borrow(); + mut_borrow_after_borrow(); + + copy_after_move_nested(); + move_after_move_nested(); + borrow_after_move_nested(); + + move_after_borrow_nested(); + + copy_after_mut_borrow_nested(); + move_after_mut_borrow_nested(); + borrow_after_mut_borrow_nested(); + mut_borrow_after_borrow_nested(); +} + diff --git a/src/test/run-pass/match-implicit-copy-unique.rs b/src/test/run-pass/match-implicit-copy-unique.rs index 679fb472503..0e7c959d58c 100644 --- a/src/test/run-pass/match-implicit-copy-unique.rs +++ b/src/test/run-pass/match-implicit-copy-unique.rs @@ -13,8 +13,9 @@ struct Pair { a: Box, b: Box } pub fn main() { let mut x = box Pair {a: box 10, b: box 20}; - match x { - box Pair {a: ref mut a, b: ref mut _b} => { + let x_internal = &mut *x; + match *x_internal { + Pair {a: ref mut a, b: ref mut _b} => { assert!(**a == 10); *a = box 30; assert!(**a == 30); } }