Skip to content

Implement RFC #43 #16102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 1, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/libcollections/treemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1564,7 +1564,8 @@ fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
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);
Expand Down
20 changes: 13 additions & 7 deletions src/libcollections/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ fn insert<T>(count: &mut uint, child: &mut Child<T>, 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 => {
Expand All @@ -799,11 +799,17 @@ fn insert<T>(count: &mut uint, child: &mut Child<T>, 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;
}
Expand All @@ -821,7 +827,7 @@ fn remove<T>(count: &mut uint, child: &mut Child<T>, 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)
Expand Down
58 changes: 56 additions & 2 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<LoanPath>) -> Rc<LoanPath> {
//! The equivalent of `owned_ptr_base_path` for an &Rc<LoanPath> 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<LoanPath>) -> Option<Rc<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.clone())
}
}
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(lp_base)
}
}
}

struct CheckLoanCtxt<'a> {
bccx: &'a BorrowckCtxt<'a>,
dfcx_loans: &'a LoanDataFlow<'a>,
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/collections/lru_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ impl<K, V> Drop for LruCache<K, V> {
unsafe {
let node: Box<LruEntry<K, V>> = 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);
}
Expand Down
9 changes: 5 additions & 4 deletions src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the year be 2012-2014?

// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -52,14 +52,15 @@ 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;
}

fn borrow_both_mut_pattern() {
let mut foo = make_foo();
match *foo {
Foo { bar1: ref mut _bar1, bar2: ref mut _bar2 } => {}
//~^ ERROR cannot borrow
}
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
Expand Down
150 changes: 150 additions & 0 deletions src/test/compile-fail/borrowck-box-insensitivity.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct A {
x: Box<int>,
y: int,
}

struct B {
x: Box<int>,
y: Box<int>,
}

struct C {
x: Box<A>,
y: int,
}

struct D {
x: Box<A>,
y: Box<int>,
}

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();
}

5 changes: 3 additions & 2 deletions src/test/run-pass/match-implicit-copy-unique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ struct Pair { a: Box<int>, b: Box<int> }

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);
}
}
Expand Down