@@ -400,50 +400,82 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
400
400
for restr_path in loan1. restricted_paths . iter ( ) {
401
401
if * restr_path != loan2_base_path { continue ; }
402
402
403
- let old_pronoun = if new_loan. loan_path == old_loan. loan_path {
403
+ // If new_loan is something like `x.a`, and old_loan is something like `x.b`, we would
404
+ // normally generate a rather confusing message (in this case, for multiple mutable
405
+ // borrows):
406
+ //
407
+ // error: cannot borrow `x.b` as mutable more than once at a time
408
+ // note: previous borrow of `x.a` occurs here; the mutable borrow prevents
409
+ // subsequent moves, borrows, or modification of `x.a` until the borrow ends
410
+ //
411
+ // What we want to do instead is get the 'common ancestor' of the two borrow paths and
412
+ // use that for most of the message instead, giving is something like this:
413
+ //
414
+ // error: cannot borrow `x` as mutable more than once at a time
415
+ // note: previous borrow of `x` occurs here (through borrowing `x.a`); the mutable
416
+ // borrow prevents subsequent moves, borrows, or modification of `x` until the
417
+ // borrow ends
418
+
419
+ let common = new_loan. loan_path . common ( & * old_loan. loan_path ) ;
420
+ let ( nl, ol, new_loan_msg, old_loan_msg) =
421
+ if new_loan. loan_path . has_fork ( & * old_loan. loan_path ) && common. is_some ( ) {
422
+ let nl = self . bccx . loan_path_to_string ( & common. unwrap ( ) ) ;
423
+ let ol = nl. clone ( ) ;
424
+ let new_loan_msg = format ! ( " (here through borrowing `{}`)" ,
425
+ self . bccx. loan_path_to_string(
426
+ & * new_loan. loan_path) ) ;
427
+ let old_loan_msg = format ! ( " (through borrowing `{}`)" ,
428
+ self . bccx. loan_path_to_string(
429
+ & * old_loan. loan_path) ) ;
430
+ ( nl, ol, new_loan_msg, old_loan_msg)
431
+ } else {
432
+ ( self . bccx . loan_path_to_string ( & * new_loan. loan_path ) ,
433
+ self . bccx . loan_path_to_string ( & * old_loan. loan_path ) ,
434
+ String :: new ( ) , String :: new ( ) )
435
+ } ;
436
+
437
+ let ol_pronoun = if new_loan. loan_path == old_loan. loan_path {
404
438
"it" . to_string ( )
405
439
} else {
406
- format ! ( "`{}`" ,
407
- self . bccx. loan_path_to_string( & * old_loan. loan_path) )
440
+ format ! ( "`{}`" , ol)
408
441
} ;
409
442
410
443
match ( new_loan. kind , old_loan. kind ) {
411
444
( ty:: MutBorrow , ty:: MutBorrow ) => {
412
445
self . bccx . span_err (
413
446
new_loan. span ,
414
- format ! ( "cannot borrow `{}` as mutable \
447
+ format ! ( "cannot borrow `{}`{} as mutable \
415
448
more than once at a time",
416
- self . bccx. loan_path_to_string(
417
- & * new_loan. loan_path) ) . as_slice ( ) ) ;
449
+ nl, new_loan_msg) . as_slice ( ) )
418
450
}
419
451
420
452
( ty:: UniqueImmBorrow , _) => {
421
453
self . bccx . span_err (
422
454
new_loan. span ,
423
455
format ! ( "closure requires unique access to `{}` \
424
- but {} is already borrowed",
425
- self . bccx. loan_path_to_string( & * new_loan. loan_path) ,
426
- old_pronoun) . as_slice ( ) ) ;
456
+ but {} is already borrowed{}",
457
+ nl, ol_pronoun, old_loan_msg) . as_slice ( ) ) ;
427
458
}
428
459
429
460
( _, ty:: UniqueImmBorrow ) => {
430
461
self . bccx . span_err (
431
462
new_loan. span ,
432
- format ! ( "cannot borrow `{}` as {} because \
463
+ format ! ( "cannot borrow `{}`{} as {} because \
433
464
previous closure requires unique access",
434
- self . bccx. loan_path_to_string( & * new_loan. loan_path) ,
435
- new_loan. kind. to_user_str( ) ) . as_slice ( ) ) ;
465
+ nl, new_loan_msg, new_loan. kind. to_user_str( ) ) . as_slice ( ) ) ;
436
466
}
437
467
438
468
( _, _) => {
439
469
self . bccx . span_err (
440
470
new_loan. span ,
441
- format ! ( "cannot borrow `{}` as {} because \
442
- {} is also borrowed as {}",
443
- self . bccx. loan_path_to_string( & * new_loan. loan_path) ,
471
+ format ! ( "cannot borrow `{}`{} as {} because \
472
+ {} is also borrowed as {}{}",
473
+ nl,
474
+ new_loan_msg,
444
475
new_loan. kind. to_user_str( ) ,
445
- old_pronoun,
446
- old_loan. kind. to_user_str( ) ) . as_slice ( ) ) ;
476
+ ol_pronoun,
477
+ old_loan. kind. to_user_str( ) ,
478
+ old_loan_msg) . as_slice ( ) ) ;
447
479
}
448
480
}
449
481
@@ -452,8 +484,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
452
484
self . bccx . span_note (
453
485
span,
454
486
format ! ( "borrow occurs due to use of `{}` in closure" ,
455
- self . bccx. loan_path_to_string(
456
- & * new_loan. loan_path) ) . as_slice ( ) ) ;
487
+ nl) . as_slice ( ) ) ;
457
488
}
458
489
_ => { }
459
490
}
@@ -463,30 +494,29 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
463
494
format ! ( "the mutable borrow prevents subsequent \
464
495
moves, borrows, or modification of `{0}` \
465
496
until the borrow ends",
466
- self . bccx. loan_path_to_string(
467
- & * old_loan. loan_path) )
497
+ ol)
468
498
}
469
499
470
500
ty:: ImmBorrow => {
471
501
format ! ( "the immutable borrow prevents subsequent \
472
502
moves or mutable borrows of `{0}` \
473
503
until the borrow ends",
474
- self . bccx . loan_path_to_string ( & * old_loan . loan_path ) )
504
+ ol )
475
505
}
476
506
477
507
ty:: UniqueImmBorrow => {
478
508
format ! ( "the unique capture prevents subsequent \
479
509
moves or borrows of `{0}` \
480
510
until the borrow ends",
481
- self . bccx . loan_path_to_string ( & * old_loan . loan_path ) )
511
+ ol )
482
512
}
483
513
} ;
484
514
485
515
let borrow_summary = match old_loan. cause {
486
516
euv:: ClosureCapture ( _) => {
487
- format ! ( "previous borrow of `{}` occurs here due to \
517
+ format ! ( "previous borrow of `{}` occurs here{} due to \
488
518
use in closure",
489
- self . bccx . loan_path_to_string ( & * old_loan . loan_path ) )
519
+ ol , old_loan_msg )
490
520
}
491
521
492
522
euv:: OverloadedOperator ( ..) |
@@ -496,8 +526,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
496
526
euv:: ForLoop ( ..) |
497
527
euv:: RefBinding ( ..) |
498
528
euv:: MatchDiscriminant ( ..) => {
499
- format ! ( "previous borrow of `{}` occurs here" ,
500
- self . bccx . loan_path_to_string ( & * old_loan . loan_path ) )
529
+ format ! ( "previous borrow of `{}` occurs here{} " ,
530
+ ol , old_loan_msg )
501
531
}
502
532
} ;
503
533
0 commit comments