Make analyze_move_out_from more field-sensitive
Currently analyze_move_out_from checks all restrictions on all base paths of the move path, but it only needs to check restrictions from loans of the base paths, and can disregard restrictions from loans of extensions of those base paths.
This commit is contained in:
parent
8c0e1ce6c9
commit
45a1b97764
@ -871,26 +871,47 @@ pub fn analyze_move_out_from(&self,
|
||||
self.tcx().map.node_to_str(expr_id),
|
||||
move_path.repr(self.tcx()));
|
||||
|
||||
// We must check every element of a move path. See
|
||||
// `borrowck-move-subcomponent.rs` for a test case.
|
||||
|
||||
let mut ret = MoveOk;
|
||||
|
||||
// First, we check for a restriction on the path P being used. This
|
||||
// accounts for borrows of P but also borrows of subpaths, like P.a.b.
|
||||
// Consider the following example:
|
||||
//
|
||||
// let x = &mut a.b.c; // Restricts a, a.b, and a.b.c
|
||||
// let y = a; // Conflicts with restriction
|
||||
|
||||
self.each_in_scope_restriction(expr_id, move_path, |loan, _restr| {
|
||||
// Any restriction prevents moves.
|
||||
ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span);
|
||||
false
|
||||
});
|
||||
|
||||
// Next, we must check for *loans* (not restrictions) on the path P or
|
||||
// any base path. This rejects examples like the following:
|
||||
//
|
||||
// let x = &mut a.b;
|
||||
// let y = a.b.c;
|
||||
//
|
||||
// Limiting this search to *loans* and not *restrictions* means that
|
||||
// examples like the following continue to work:
|
||||
//
|
||||
// let x = &mut a.b;
|
||||
// let y = a.c;
|
||||
|
||||
let mut loan_path = move_path;
|
||||
loop {
|
||||
// check for a conflicting loan:
|
||||
self.each_in_scope_restriction(expr_id, loan_path, |loan, _| {
|
||||
self.each_in_scope_loan(expr_id, |loan| {
|
||||
// Any restriction prevents moves.
|
||||
ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span);
|
||||
false
|
||||
if *loan.loan_path == *loan_path {
|
||||
ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
if ret != MoveOk {
|
||||
return ret
|
||||
}
|
||||
|
||||
match *loan_path {
|
||||
LpVar(_) => {
|
||||
ret = MoveOk;
|
||||
break;
|
||||
}
|
||||
LpExtend(ref lp_base, _, _) => {
|
||||
@ -898,6 +919,7 @@ pub fn analyze_move_out_from(&self,
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -84,20 +84,6 @@ fn fu_move_after_fu_move() {
|
||||
|
||||
// The following functions aren't yet accepted, but they should be.
|
||||
|
||||
fn move_after_borrow_correct() {
|
||||
let x = A { a: 1, b: box 2 };
|
||||
let p = &x.a;
|
||||
drop(x.b); //~ ERROR cannot move out of `x.b` because it is borrowed
|
||||
drop(*p);
|
||||
}
|
||||
|
||||
fn fu_move_after_borrow_correct() {
|
||||
let x = A { a: 1, b: box 2 };
|
||||
let p = &x.a;
|
||||
let _y = A { a: 3, .. x }; //~ ERROR cannot move out of `x.b` because it is borrowed
|
||||
drop(*p);
|
||||
}
|
||||
|
||||
fn copy_after_field_assign_after_uninit() {
|
||||
let mut x: A;
|
||||
x.a = 1;
|
||||
@ -132,9 +118,6 @@ fn main() {
|
||||
fu_move_after_move();
|
||||
fu_move_after_fu_move();
|
||||
|
||||
move_after_borrow_correct();
|
||||
fu_move_after_borrow_correct();
|
||||
|
||||
copy_after_field_assign_after_uninit();
|
||||
borrow_after_field_assign_after_uninit();
|
||||
move_after_field_assign_after_uninit();
|
||||
|
@ -73,6 +73,20 @@ fn borrow_after_fu_move() {
|
||||
drop(*p);
|
||||
}
|
||||
|
||||
fn move_after_borrow() {
|
||||
let x = A { a: 1, b: box 2 };
|
||||
let p = &x.a;
|
||||
drop(x.b);
|
||||
drop(*p);
|
||||
}
|
||||
|
||||
fn fu_move_after_borrow() {
|
||||
let x = A { a: 1, b: box 2 };
|
||||
let p = &x.a;
|
||||
let _y = A { a: 3, .. x };
|
||||
drop(*p);
|
||||
}
|
||||
|
||||
fn mut_borrow_after_mut_borrow() {
|
||||
let mut x = A { a: 1, b: box 2 };
|
||||
let p = &mut x.a;
|
||||
@ -225,6 +239,8 @@ fn main() {
|
||||
|
||||
borrow_after_move();
|
||||
borrow_after_fu_move();
|
||||
move_after_borrow();
|
||||
fu_move_after_borrow();
|
||||
mut_borrow_after_mut_borrow();
|
||||
|
||||
move_after_move();
|
||||
|
Loading…
Reference in New Issue
Block a user