@@ -447,49 +447,105 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
447447 // borrow ends
448448
449449 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) = {
451451 if new_loan. loan_path . has_fork ( & old_loan. loan_path ) && common. is_some ( ) {
452452 let nl = self . bccx . loan_path_to_string ( & common. unwrap ( ) ) ;
453453 let ol = nl. clone ( ) ;
454- let new_loan_msg = format ! ( " (here through borrowing `{}`)" ,
454+ let new_loan_msg = format ! ( " (via `{}`)" ,
455455 self . bccx. loan_path_to_string(
456456 & new_loan. loan_path) ) ;
457- let old_loan_msg = format ! ( " (through borrowing `{}`)" ,
457+ let old_loan_msg = format ! ( " (via `{}`)" ,
458458 self . bccx. loan_path_to_string(
459459 & old_loan. loan_path) ) ;
460460 ( nl, ol, new_loan_msg, old_loan_msg)
461461 } else {
462462 ( self . bccx . loan_path_to_string ( & new_loan. loan_path ) ,
463463 self . bccx . loan_path_to_string ( & old_loan. loan_path ) ,
464- String :: new ( ) , String :: new ( ) )
465- } ;
464+ String :: new ( ) ,
465+ String :: new ( ) )
466+ }
467+ } ;
466468
467469 let ol_pronoun = if new_loan. loan_path == old_loan. loan_path {
468470 "it" . to_string ( )
469471 } else {
470472 format ! ( "`{}`" , ol)
471473 } ;
472474
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+
473486 let mut err = match ( new_loan. kind , old_loan. kind ) {
474487 ( ty:: MutBorrow , ty:: MutBorrow ) => {
475488 struct_span_err ! ( self . bccx, new_loan. span, E0499 ,
476489 "cannot borrow `{}`{} as mutable \
477490 more than once at a time",
478491 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" ) )
479517 }
480518
481519 ( ty:: UniqueImmBorrow , _) => {
482520 struct_span_err ! ( self . bccx, new_loan. span, E0500 ,
483521 "closure requires unique access to `{}` \
484522 but {} is already borrowed{}",
485523 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" ) )
486533 }
487534
488535 ( _, ty:: UniqueImmBorrow ) => {
489536 struct_span_err ! ( self . bccx, new_loan. span, E0501 ,
490537 "cannot borrow `{}`{} as {} because \
491538 previous closure requires unique access",
492539 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" ) )
493549 }
494550
495551 ( _, _) => {
@@ -502,70 +558,42 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
502558 ol_pronoun,
503559 old_loan. kind. to_user_str( ) ,
504560 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( ) ) )
505575 }
506576 } ;
507577
508578 match new_loan. cause {
509579 euv:: ClosureCapture ( span) => {
510- err. span_note (
580+ err = err . span_label (
511581 span,
512- & format ! ( "borrow occurs due to use of `{}` in closure" ,
513- nl) ) ;
582+ & format ! ( "borrow occurs due to use of `{}` in closure" , nl) ) ;
514583 }
515584 _ => { }
516585 }
517586
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) ) ;
558593 }
559- } ;
560-
561- err. span_note (
562- old_loan. span ,
563- & format ! ( "{}; {}" , borrow_summary, rule_summary) ) ;
594+ _ => { }
595+ }
564596
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" ) ;
569597 err. emit ( ) ;
570598 return false ;
571599 }
0 commit comments