Skip to content

Commit

Permalink
Add a new each_in_scope_loan_affecting_path helper function
Browse files Browse the repository at this point in the history
Add a helper function that generalizes the loan path restriction
strategy used by analyze_restrictions_on_use.
  • Loading branch information
Cameron Zwarich committed Jun 16, 2014
1 parent e018fc3 commit ba203c5
Showing 1 changed file with 72 additions and 42 deletions.
114 changes: 72 additions & 42 deletions src/librustc/middle/borrowck/check_loans.rs
Expand Up @@ -220,6 +220,77 @@ impl<'a> CheckLoanCtxt<'a> {
})
}

fn each_in_scope_loan_affecting_path(&self,
scope_id: ast::NodeId,
loan_path: &LoanPath,
op: |&Loan| -> bool)
-> bool {
//! Iterates through all of the in-scope loans affecting `loan_path`,
//! calling `op`, and ceasing iteration if `false` is returned.

// First, we check for a loan restricting 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

let cont = self.each_in_scope_loan(scope_id, |loan| {
let mut ret = true;
for restr_path in loan.restricted_paths.iter() {
if **restr_path == *loan_path {
if !op(loan) {
ret = false;
break;
}
}
}
ret
});

if !cont {
return 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 = loan_path;
loop {
match *loan_path {
LpVar(_) => {
break;
}
LpExtend(ref lp_base, _, _) => {
loan_path = &**lp_base;
}
}

let cont = self.each_in_scope_loan(scope_id, |loan| {
if *loan.loan_path == *loan_path {
op(loan)
} else {
true
}
});

if !cont {
return false;
}
}

return true;
}

pub fn loans_generated_by(&self, scope_id: ast::NodeId) -> Vec<uint> {
//! Returns a vector of the loans that are generated as
//! we encounter `scope_id`.
Expand Down Expand Up @@ -526,14 +597,7 @@ impl<'a> CheckLoanCtxt<'a> {

let mut ret = UseOk;

// 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, use_path, |loan| {
self.each_in_scope_loan_affecting_path(expr_id, use_path, |loan| {
if !compatible_borrow_kinds(loan.kind, borrow_kind) {
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
false
Expand All @@ -542,40 +606,6 @@ impl<'a> CheckLoanCtxt<'a> {
}
});

// 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 = use_path;
loop {
self.each_in_scope_loan(expr_id, |loan| {
if *loan.loan_path == *loan_path &&
!compatible_borrow_kinds(loan.kind, borrow_kind) {
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
false
} else {
true
}
});

match *loan_path {
LpVar(_) => {
break;
}
LpExtend(ref lp_base, _, _) => {
loan_path = &**lp_base;
}
}
}

return ret;
}

Expand Down

0 comments on commit ba203c5

Please sign in to comment.