@@ -447,49 +447,105 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
447
447
// borrow ends
448
448
449
449
let common = new_loan. loan_path . common ( & old_loan. loan_path ) ;
450
- let ( nl, ol, new_loan_msg, old_loan_msg) =
450
+ let ( nl, ol, new_loan_msg, old_loan_msg) = {
451
451
if new_loan. loan_path . has_fork ( & old_loan. loan_path ) && common. is_some ( ) {
452
452
let nl = self . bccx . loan_path_to_string ( & common. unwrap ( ) ) ;
453
453
let ol = nl. clone ( ) ;
454
- let new_loan_msg = format ! ( " (here through borrowing `{}`)" ,
454
+ let new_loan_msg = format ! ( " (via `{}`)" ,
455
455
self . bccx. loan_path_to_string(
456
456
& new_loan. loan_path) ) ;
457
- let old_loan_msg = format ! ( " (through borrowing `{}`)" ,
457
+ let old_loan_msg = format ! ( " (via `{}`)" ,
458
458
self . bccx. loan_path_to_string(
459
459
& old_loan. loan_path) ) ;
460
460
( nl, ol, new_loan_msg, old_loan_msg)
461
461
} else {
462
462
( self . bccx . loan_path_to_string ( & new_loan. loan_path ) ,
463
463
self . bccx . loan_path_to_string ( & old_loan. loan_path ) ,
464
- String :: new ( ) , String :: new ( ) )
465
- } ;
464
+ String :: new ( ) ,
465
+ String :: new ( ) )
466
+ }
467
+ } ;
466
468
467
469
let ol_pronoun = if new_loan. loan_path == old_loan. loan_path {
468
470
"it" . to_string ( )
469
471
} else {
470
472
format ! ( "`{}`" , ol)
471
473
} ;
472
474
475
+ // We want to assemble all the relevant locations for the error.
476
+ //
477
+ // 1. Where did the new loan occur.
478
+ // - if due to closure creation, where was the variable used in closure?
479
+ // 2. Where did old loan occur.
480
+ // 3. Where does old loan expire.
481
+
482
+ let previous_end_span =
483
+ self . tcx ( ) . map . span ( old_loan. kill_scope . node_id ( & self . tcx ( ) . region_maps ) )
484
+ . end_point ( ) ;
485
+
473
486
let mut err = match ( new_loan. kind , old_loan. kind ) {
474
487
( ty:: MutBorrow , ty:: MutBorrow ) => {
475
488
struct_span_err ! ( self . bccx, new_loan. span, E0499 ,
476
489
"cannot borrow `{}`{} as mutable \
477
490
more than once at a time",
478
491
nl, new_loan_msg)
492
+ . span_label (
493
+ old_loan. span ,
494
+ & format ! ( "first mutable borrow occurs here{}" , old_loan_msg) )
495
+ . span_label (
496
+ new_loan. span ,
497
+ & format ! ( "second mutable borrow occurs here{}" , new_loan_msg) )
498
+ . span_label (
499
+ previous_end_span,
500
+ & format ! ( "first borrow ends here" ) )
501
+ }
502
+
503
+ ( ty:: UniqueImmBorrow , ty:: UniqueImmBorrow ) => {
504
+ struct_span_err ! ( self . bccx, new_loan. span, E0524 ,
505
+ "two closures require unique access to `{}` \
506
+ at the same time",
507
+ nl)
508
+ . span_label (
509
+ old_loan. span ,
510
+ & format ! ( "first closure is constructed here" ) )
511
+ . span_label (
512
+ new_loan. span ,
513
+ & format ! ( "second closure is constructed here" ) )
514
+ . span_label (
515
+ previous_end_span,
516
+ & format ! ( "borrow from first closure ends here" ) )
479
517
}
480
518
481
519
( ty:: UniqueImmBorrow , _) => {
482
520
struct_span_err ! ( self . bccx, new_loan. span, E0500 ,
483
521
"closure requires unique access to `{}` \
484
522
but {} is already borrowed{}",
485
523
nl, ol_pronoun, old_loan_msg)
524
+ . span_label (
525
+ new_loan. span ,
526
+ & format ! ( "closure construction occurs here{}" , new_loan_msg) )
527
+ . span_label (
528
+ old_loan. span ,
529
+ & format ! ( "borrow occurs here{}" , old_loan_msg) )
530
+ . span_label (
531
+ previous_end_span,
532
+ & format ! ( "borrow ends here" ) )
486
533
}
487
534
488
535
( _, ty:: UniqueImmBorrow ) => {
489
536
struct_span_err ! ( self . bccx, new_loan. span, E0501 ,
490
537
"cannot borrow `{}`{} as {} because \
491
538
previous closure requires unique access",
492
539
nl, new_loan_msg, new_loan. kind. to_user_str( ) )
540
+ . span_label (
541
+ new_loan. span ,
542
+ & format ! ( "borrow occurs here{}" , new_loan_msg) )
543
+ . span_label (
544
+ old_loan. span ,
545
+ & format ! ( "closure construction occurs here{}" , old_loan_msg) )
546
+ . span_label (
547
+ previous_end_span,
548
+ & format ! ( "borrow from closure ends here" ) )
493
549
}
494
550
495
551
( _, _) => {
@@ -502,70 +558,42 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
502
558
ol_pronoun,
503
559
old_loan. kind. to_user_str( ) ,
504
560
old_loan_msg)
561
+ . span_label (
562
+ new_loan. span ,
563
+ & format ! ( "{} borrow occurs here{}" ,
564
+ new_loan. kind. to_user_str( ) ,
565
+ new_loan_msg) )
566
+ . span_label (
567
+ old_loan. span ,
568
+ & format ! ( "{} borrow occurs here{}" ,
569
+ old_loan. kind. to_user_str( ) ,
570
+ old_loan_msg) )
571
+ . span_label (
572
+ previous_end_span,
573
+ & format ! ( "{} borrow ends here" ,
574
+ old_loan. kind. to_user_str( ) ) )
505
575
}
506
576
} ;
507
577
508
578
match new_loan. cause {
509
579
euv:: ClosureCapture ( span) => {
510
- err. span_note (
580
+ err = err . span_label (
511
581
span,
512
- & format ! ( "borrow occurs due to use of `{}` in closure" ,
513
- nl) ) ;
582
+ & format ! ( "borrow occurs due to use of `{}` in closure" , nl) ) ;
514
583
}
515
584
_ => { }
516
585
}
517
586
518
- let rule_summary = match old_loan. kind {
519
- ty:: MutBorrow => {
520
- format ! ( "the mutable borrow prevents subsequent \
521
- moves, borrows, or modification of `{0}` \
522
- until the borrow ends",
523
- ol)
524
- }
525
-
526
- ty:: ImmBorrow => {
527
- format ! ( "the immutable borrow prevents subsequent \
528
- moves or mutable borrows of `{0}` \
529
- until the borrow ends",
530
- ol)
531
- }
532
-
533
- ty:: UniqueImmBorrow => {
534
- format ! ( "the unique capture prevents subsequent \
535
- moves or borrows of `{0}` \
536
- until the borrow ends",
537
- ol)
538
- }
539
- } ;
540
-
541
- let borrow_summary = match old_loan. cause {
542
- euv:: ClosureCapture ( _) => {
543
- format ! ( "previous borrow of `{}` occurs here{} due to \
544
- use in closure",
545
- ol, old_loan_msg)
546
- }
547
-
548
- euv:: OverloadedOperator |
549
- euv:: AddrOf |
550
- euv:: AutoRef |
551
- euv:: AutoUnsafe |
552
- euv:: ClosureInvocation |
553
- euv:: ForLoop |
554
- euv:: RefBinding |
555
- euv:: MatchDiscriminant => {
556
- format ! ( "previous borrow of `{}` occurs here{}" ,
557
- ol, old_loan_msg)
587
+ match old_loan. cause {
588
+ euv:: ClosureCapture ( span) => {
589
+ err = err. span_label (
590
+ span,
591
+ & format ! ( "previous borrow occurs due to use of `{}` in closure" ,
592
+ ol) ) ;
558
593
}
559
- } ;
560
-
561
- err. span_note (
562
- old_loan. span ,
563
- & format ! ( "{}; {}" , borrow_summary, rule_summary) ) ;
594
+ _ => { }
595
+ }
564
596
565
- let old_loan_span = self . tcx ( ) . map . span (
566
- old_loan. kill_scope . node_id ( & self . tcx ( ) . region_maps ) ) ;
567
- err. span_end_note ( old_loan_span,
568
- "previous borrow ends here" ) ;
569
597
err. emit ( ) ;
570
598
return false ;
571
599
}
0 commit comments