diff options
| author | Cameron Zwarich <zwarich@mozilla.com> | 2014-06-13 20:48:09 -0700 |
|---|---|---|
| committer | Cameron Zwarich <zwarich@mozilla.com> | 2014-06-13 20:48:09 -0700 |
| commit | 45a1b977643456ceacfc81183e2d5743f7c61ce9 (patch) | |
| tree | 94e71110ec115abe06df393c2b1000c3f9da4b92 | |
| parent | 8c0e1ce6c9410f4d928923ee93e7b5a4674ae2ed (diff) | |
| download | rust-45a1b977643456ceacfc81183e2d5743f7c61ce9.tar.gz rust-45a1b977643456ceacfc81183e2d5743f7c61ce9.zip | |
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.
| -rw-r--r-- | src/librustc/middle/borrowck/check_loans.rs | 48 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-field-sensitivity.rs | 17 | ||||
| -rw-r--r-- | src/test/run-pass/borrowck-field-sensitivity.rs | 16 |
3 files changed, 51 insertions, 30 deletions
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 45d15a9afac..ab004e4a3e9 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -871,26 +871,47 @@ impl<'a> CheckLoanCtxt<'a> { 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 @@ impl<'a> CheckLoanCtxt<'a> { } } } - ret + + return ret; } } diff --git a/src/test/compile-fail/borrowck-field-sensitivity.rs b/src/test/compile-fail/borrowck-field-sensitivity.rs index 2fa9067af54..72042b8373d 100644 --- a/src/test/compile-fail/borrowck-field-sensitivity.rs +++ b/src/test/compile-fail/borrowck-field-sensitivity.rs @@ -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(); diff --git a/src/test/run-pass/borrowck-field-sensitivity.rs b/src/test/run-pass/borrowck-field-sensitivity.rs index a297300daf1..33be47e504b 100644 --- a/src/test/run-pass/borrowck-field-sensitivity.rs +++ b/src/test/run-pass/borrowck-field-sensitivity.rs @@ -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(); |
