@@ -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