@@ -220,6 +220,77 @@ impl<'a> CheckLoanCtxt<'a> {
220
220
} )
221
221
}
222
222
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
+
223
294
pub fn loans_generated_by ( & self , scope_id : ast:: NodeId ) -> Vec < uint > {
224
295
//! Returns a vector of the loans that are generated as
225
296
//! we encounter `scope_id`.
@@ -526,14 +597,7 @@ impl<'a> CheckLoanCtxt<'a> {
526
597
527
598
let mut ret = UseOk ;
528
599
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| {
537
601
if !compatible_borrow_kinds ( loan. kind , borrow_kind) {
538
602
ret = UseWhileBorrowed ( loan. loan_path . clone ( ) , loan. span ) ;
539
603
false
@@ -542,40 +606,6 @@ impl<'a> CheckLoanCtxt<'a> {
542
606
}
543
607
} ) ;
544
608
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
-
579
609
return ret;
580
610
}
581
611
0 commit comments