Skip to content

Commit

Permalink
add borrowck info inline in main snippet
Browse files Browse the repository at this point in the history
This uses the new `span_label` APIs
  • Loading branch information
nikomatsakis committed May 2, 2016
1 parent e7c7a18 commit 5b150cf
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 187 deletions.
2 changes: 1 addition & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1569,5 +1569,5 @@ register_diagnostics! {
E0490, // a value of type `..` is borrowed for too long
E0491, // in type `..`, reference has a longer lifetime than the data it...
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
E0524, // expected a closure that implements `..` but this closure only implements `..`
E0525, // expected a closure that implements `..` but this closure only implements `..`
}
142 changes: 85 additions & 57 deletions src/librustc_borrowck/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,49 +447,105 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
// borrow ends

let common = new_loan.loan_path.common(&old_loan.loan_path);
let (nl, ol, new_loan_msg, old_loan_msg) =
let (nl, ol, new_loan_msg, old_loan_msg) = {
if new_loan.loan_path.has_fork(&old_loan.loan_path) && common.is_some() {
let nl = self.bccx.loan_path_to_string(&common.unwrap());
let ol = nl.clone();
let new_loan_msg = format!(" (here through borrowing `{}`)",
let new_loan_msg = format!(" (via `{}`)",
self.bccx.loan_path_to_string(
&new_loan.loan_path));
let old_loan_msg = format!(" (through borrowing `{}`)",
let old_loan_msg = format!(" (via `{}`)",
self.bccx.loan_path_to_string(
&old_loan.loan_path));
(nl, ol, new_loan_msg, old_loan_msg)
} else {
(self.bccx.loan_path_to_string(&new_loan.loan_path),
self.bccx.loan_path_to_string(&old_loan.loan_path),
String::new(), String::new())
};
String::new(),
String::new())
}
};

let ol_pronoun = if new_loan.loan_path == old_loan.loan_path {
"it".to_string()
} else {
format!("`{}`", ol)
};

// We want to assemble all the relevant locations for the error.
//
// 1. Where did the new loan occur.
// - if due to closure creation, where was the variable used in closure?
// 2. Where did old loan occur.
// 3. Where does old loan expire.

let previous_end_span =
self.tcx().map.span(old_loan.kill_scope.node_id(&self.tcx().region_maps))
.end_point();

let mut err = match (new_loan.kind, old_loan.kind) {
(ty::MutBorrow, ty::MutBorrow) => {
struct_span_err!(self.bccx, new_loan.span, E0499,
"cannot borrow `{}`{} as mutable \
more than once at a time",
nl, new_loan_msg)
.span_label(
old_loan.span,
&format!("first mutable borrow occurs here{}", old_loan_msg))
.span_label(
new_loan.span,
&format!("second mutable borrow occurs here{}", new_loan_msg))
.span_label(
previous_end_span,
&format!("first borrow ends here"))
}

(ty::UniqueImmBorrow, ty::UniqueImmBorrow) => {
struct_span_err!(self.bccx, new_loan.span, E0524,
"two closures require unique access to `{}` \
at the same time",
nl)
.span_label(
old_loan.span,
&format!("first closure is constructed here"))
.span_label(
new_loan.span,
&format!("second closure is constructed here"))
.span_label(
previous_end_span,
&format!("borrow from first closure ends here"))
}

(ty::UniqueImmBorrow, _) => {
struct_span_err!(self.bccx, new_loan.span, E0500,
"closure requires unique access to `{}` \
but {} is already borrowed{}",
nl, ol_pronoun, old_loan_msg)
.span_label(
new_loan.span,
&format!("closure construction occurs here{}", new_loan_msg))
.span_label(
old_loan.span,
&format!("borrow occurs here{}", old_loan_msg))
.span_label(
previous_end_span,
&format!("borrow ends here"))
}

(_, ty::UniqueImmBorrow) => {
struct_span_err!(self.bccx, new_loan.span, E0501,
"cannot borrow `{}`{} as {} because \
previous closure requires unique access",
nl, new_loan_msg, new_loan.kind.to_user_str())
.span_label(
new_loan.span,
&format!("borrow occurs here{}", new_loan_msg))
.span_label(
old_loan.span,
&format!("closure construction occurs here{}", old_loan_msg))
.span_label(
previous_end_span,
&format!("borrow from closure ends here"))
}

(_, _) => {
Expand All @@ -502,70 +558,42 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
ol_pronoun,
old_loan.kind.to_user_str(),
old_loan_msg)
.span_label(
new_loan.span,
&format!("{} borrow occurs here{}",
new_loan.kind.to_user_str(),
new_loan_msg))
.span_label(
old_loan.span,
&format!("{} borrow occurs here{}",
old_loan.kind.to_user_str(),
old_loan_msg))
.span_label(
previous_end_span,
&format!("{} borrow ends here",
old_loan.kind.to_user_str()))
}
};

match new_loan.cause {
euv::ClosureCapture(span) => {
err.span_note(
err = err.span_label(
span,
&format!("borrow occurs due to use of `{}` in closure",
nl));
&format!("borrow occurs due to use of `{}` in closure", nl));
}
_ => { }
}

let rule_summary = match old_loan.kind {
ty::MutBorrow => {
format!("the mutable borrow prevents subsequent \
moves, borrows, or modification of `{0}` \
until the borrow ends",
ol)
}

ty::ImmBorrow => {
format!("the immutable borrow prevents subsequent \
moves or mutable borrows of `{0}` \
until the borrow ends",
ol)
}

ty::UniqueImmBorrow => {
format!("the unique capture prevents subsequent \
moves or borrows of `{0}` \
until the borrow ends",
ol)
}
};

let borrow_summary = match old_loan.cause {
euv::ClosureCapture(_) => {
format!("previous borrow of `{}` occurs here{} due to \
use in closure",
ol, old_loan_msg)
}

euv::OverloadedOperator |
euv::AddrOf |
euv::AutoRef |
euv::AutoUnsafe |
euv::ClosureInvocation |
euv::ForLoop |
euv::RefBinding |
euv::MatchDiscriminant => {
format!("previous borrow of `{}` occurs here{}",
ol, old_loan_msg)
match old_loan.cause {
euv::ClosureCapture(span) => {
err = err.span_label(
span,
&format!("previous borrow occurs due to use of `{}` in closure",
ol));
}
};

err.span_note(
old_loan.span,
&format!("{}; {}", borrow_summary, rule_summary));
_ => { }
}

let old_loan_span = self.tcx().map.span(
old_loan.kill_scope.node_id(&self.tcx().region_maps));
err.span_end_note(old_loan_span,
"previous borrow ends here");
err.emit();
return false;
}
Expand Down
Loading

0 comments on commit 5b150cf

Please sign in to comment.