Skip to content

Commit ba203c5

Browse files
author
Cameron Zwarich
committed
Add a new each_in_scope_loan_affecting_path helper function
Add a helper function that generalizes the loan path restriction strategy used by analyze_restrictions_on_use.
1 parent e018fc3 commit ba203c5

File tree

1 file changed

+72
-42
lines changed

1 file changed

+72
-42
lines changed

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,77 @@ impl<'a> CheckLoanCtxt<'a> {
220220
})
221221
}
222222

223+
fn each_in_scope_loan_affecting_path(&self,
224+
scope_id: ast::NodeId,
225+
loan_path: &LoanPath,
226+
op: |&Loan| -> bool)
227+
-> bool {
228+
//! Iterates through all of the in-scope loans affecting `loan_path`,
229+
//! calling `op`, and ceasing iteration if `false` is returned.
230+
231+
// First, we check for a loan restricting the path P being used. This
232+
// accounts for borrows of P but also borrows of subpaths, like P.a.b.
233+
// Consider the following example:
234+
//
235+
// let x = &mut a.b.c; // Restricts a, a.b, and a.b.c
236+
// let y = a; // Conflicts with restriction
237+
238+
let cont = self.each_in_scope_loan(scope_id, |loan| {
239+
let mut ret = true;
240+
for restr_path in loan.restricted_paths.iter() {
241+
if **restr_path == *loan_path {
242+
if !op(loan) {
243+
ret = false;
244+
break;
245+
}
246+
}
247+
}
248+
ret
249+
});
250+
251+
if !cont {
252+
return false;
253+
}
254+
255+
// Next, we must check for *loans* (not restrictions) on the path P or
256+
// any base path. This rejects examples like the following:
257+
//
258+
// let x = &mut a.b;
259+
// let y = a.b.c;
260+
//
261+
// Limiting this search to *loans* and not *restrictions* means that
262+
// examples like the following continue to work:
263+
//
264+
// let x = &mut a.b;
265+
// let y = a.c;
266+
267+
let mut loan_path = loan_path;
268+
loop {
269+
match *loan_path {
270+
LpVar(_) => {
271+
break;
272+
}
273+
LpExtend(ref lp_base, _, _) => {
274+
loan_path = &**lp_base;
275+
}
276+
}
277+
278+
let cont = self.each_in_scope_loan(scope_id, |loan| {
279+
if *loan.loan_path == *loan_path {
280+
op(loan)
281+
} else {
282+
true
283+
}
284+
});
285+
286+
if !cont {
287+
return false;
288+
}
289+
}
290+
291+
return true;
292+
}
293+
223294
pub fn loans_generated_by(&self, scope_id: ast::NodeId) -> Vec<uint> {
224295
//! Returns a vector of the loans that are generated as
225296
//! we encounter `scope_id`.
@@ -526,14 +597,7 @@ impl<'a> CheckLoanCtxt<'a> {
526597

527598
let mut ret = UseOk;
528599

529-
// First, we check for a restriction on the path P being used. This
530-
// accounts for borrows of P but also borrows of subpaths, like P.a.b.
531-
// Consider the following example:
532-
//
533-
// let x = &mut a.b.c; // Restricts a, a.b, and a.b.c
534-
// let y = a; // Conflicts with restriction
535-
536-
self.each_in_scope_restriction(expr_id, use_path, |loan| {
600+
self.each_in_scope_loan_affecting_path(expr_id, use_path, |loan| {
537601
if !compatible_borrow_kinds(loan.kind, borrow_kind) {
538602
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
539603
false
@@ -542,40 +606,6 @@ impl<'a> CheckLoanCtxt<'a> {
542606
}
543607
});
544608

545-
// Next, we must check for *loans* (not restrictions) on the path P or
546-
// any base path. This rejects examples like the following:
547-
//
548-
// let x = &mut a.b;
549-
// let y = a.b.c;
550-
//
551-
// Limiting this search to *loans* and not *restrictions* means that
552-
// examples like the following continue to work:
553-
//
554-
// let x = &mut a.b;
555-
// let y = a.c;
556-
557-
let mut loan_path = use_path;
558-
loop {
559-
self.each_in_scope_loan(expr_id, |loan| {
560-
if *loan.loan_path == *loan_path &&
561-
!compatible_borrow_kinds(loan.kind, borrow_kind) {
562-
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
563-
false
564-
} else {
565-
true
566-
}
567-
});
568-
569-
match *loan_path {
570-
LpVar(_) => {
571-
break;
572-
}
573-
LpExtend(ref lp_base, _, _) => {
574-
loan_path = &**lp_base;
575-
}
576-
}
577-
}
578-
579609
return ret;
580610
}
581611

0 commit comments

Comments
 (0)