Skip to content

Commit 5b150cf

Browse files
committed
add borrowck info inline in main snippet
This uses the new `span_label` APIs
1 parent e7c7a18 commit 5b150cf

File tree

4 files changed

+146
-187
lines changed

4 files changed

+146
-187
lines changed

src/librustc/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1569,5 +1569,5 @@ register_diagnostics! {
15691569
E0490, // a value of type `..` is borrowed for too long
15701570
E0491, // in type `..`, reference has a longer lifetime than the data it...
15711571
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
1572-
E0524, // expected a closure that implements `..` but this closure only implements `..`
1572+
E0525, // expected a closure that implements `..` but this closure only implements `..`
15731573
}

src/librustc_borrowck/borrowck/check_loans.rs

+85-57
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)