combine bckerr_to_diag and note_and_explain_bckerr

This commit is contained in:
Niko Matsakis 2017-07-15 05:18:19 -04:00 committed by John Kåre Alsaker
parent 5a6e0694da
commit 188cdf499f

View File

@ -506,9 +506,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
_ => { }
}
let mut db = self.bckerr_to_diag(&err);
self.note_and_explain_bckerr(&mut db, err);
db.emit();
self.report_bckerr(&err);
}
pub fn report_use_of_moved_value(&self,
@ -693,8 +691,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
self.tcx.sess.span_err_with_code(s, msg, code);
}
fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
let span = err.span.clone();
fn report_bckerr(&self, err: &BckError<'tcx>) {
let error_span = err.span.clone();
match err.code {
err_mutbl => {
@ -718,12 +716,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
};
match err.cause {
let mut db = match err.cause {
MutabilityViolation => {
struct_span_err!(self.tcx.sess, span, E0594, "cannot assign to {}", descr)
struct_span_err!(self.tcx.sess, error_span, E0594, "cannot assign to {}", descr)
}
BorrowViolation(euv::ClosureCapture(_)) => {
struct_span_err!(self.tcx.sess, span, E0595,
struct_span_err!(self.tcx.sess, error_span, E0595,
"closure cannot assign to {}", descr)
}
BorrowViolation(euv::OverloadedOperator) |
@ -733,30 +731,152 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
BorrowViolation(euv::AutoUnsafe) |
BorrowViolation(euv::ForLoop) |
BorrowViolation(euv::MatchDiscriminant) => {
struct_span_err!(self.tcx.sess, span, E0596,
struct_span_err!(self.tcx.sess, error_span, E0596,
"cannot borrow {} as mutable", descr)
}
BorrowViolation(euv::ClosureInvocation) => {
span_bug!(err.span,
"err_mutbl with a closure invocation");
}
}
};
self.note_and_explain_mutbl_error(&mut db, &err, &error_span);
self.note_immutability_blame(&mut db, err.cmt.immutability_blame());
db.emit();
}
err_out_of_scope(..) => {
err_out_of_scope(super_scope, sub_scope, cause) => {
let msg = match opt_loan_path(&err.cmt) {
None => "borrowed value".to_string(),
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
};
struct_span_err!(self.tcx.sess, span, E0597, "{} does not live long enough", msg)
let mut db = struct_span_err!(self.tcx.sess, error_span, E0597, "{} does not live long enough", msg);
let (value_kind, value_msg) = match err.cmt.cat {
mc::Categorization::Rvalue(..) =>
("temporary value", "temporary value created here"),
_ =>
("borrowed value", "borrow occurs here")
};
let is_closure = match cause {
euv::ClosureCapture(s) => {
// The primary span starts out as the closure creation point.
// Change the primary span here to highlight the use of the variable
// in the closure, because it seems more natural. Highlight
// closure creation point as a secondary span.
match db.span.primary_span() {
Some(primary) => {
db.span = MultiSpan::from_span(s);
db.span_label(primary, "capture occurs here");
db.span_label(s, "does not live long enough");
true
}
None => false
}
}
_ => {
db.span_label(error_span, "does not live long enough");
false
}
};
let sub_span = self.region_end_span(sub_scope);
let super_span = self.region_end_span(super_scope);
match (sub_span, super_span) {
(Some(s1), Some(s2)) if s1 == s2 => {
if !is_closure {
db.span = MultiSpan::from_span(s1);
db.span_label(error_span, value_msg);
let msg = match opt_loan_path(&err.cmt) {
None => value_kind.to_string(),
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
};
db.span_label(s1,
format!("{} dropped here while still borrowed", msg));
} else {
db.span_label(s1, format!("{} dropped before borrower", value_kind));
}
db.note("values in a scope are dropped in the opposite order \
they are created");
}
(Some(s1), Some(s2)) if !is_closure => {
db.span = MultiSpan::from_span(s2);
db.span_label(error_span, value_msg);
let msg = match opt_loan_path(&err.cmt) {
None => value_kind.to_string(),
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
};
db.span_label(s2, format!("{} dropped here while still borrowed", msg));
db.span_label(s1, format!("{} needs to live until here", value_kind));
}
_ => {
match sub_span {
Some(s) => {
db.span_label(s, format!("{} needs to live until here",
value_kind));
}
None => {
self.tcx.note_and_explain_region(
&mut db,
"borrowed value must be valid for ",
sub_scope,
"...");
}
}
match super_span {
Some(s) => {
db.span_label(s, format!("{} only lives until here", value_kind));
}
None => {
self.tcx.note_and_explain_region(
&mut db,
"...but borrowed value is only valid for ",
super_scope,
"");
}
}
}
}
if let Some(_) = statement_scope_span(self.tcx, super_scope) {
db.note("consider using a `let` binding to increase its lifetime");
}
db.emit();
}
err_borrowed_pointer_too_short(..) => {
err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
let descr = self.cmt_to_path_or_string(&err.cmt);
struct_span_err!(self.tcx.sess, span, E0598,
"lifetime of {} is too short to guarantee \
its contents can be safely reborrowed",
descr)
let mut db = struct_span_err!(self.tcx.sess, error_span, E0598,
"lifetime of {} is too short to guarantee \
its contents can be safely reborrowed",
descr);
let descr = match opt_loan_path(&err.cmt) {
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
None => self.cmt_to_string(&err.cmt),
};
self.tcx.note_and_explain_region(
&mut db,
&format!("{} would have to be valid for ",
descr),
loan_scope,
"...");
self.tcx.note_and_explain_region(
&mut db,
&format!("...but {} is only valid for ", descr),
ptr_scope,
"");
db.emit();
}
}
}
@ -1013,133 +1133,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
}
fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>) {
let error_span = err.span.clone();
match err.code {
err_mutbl => {
self.note_and_explain_mutbl_error(db, &err, &error_span);
self.note_immutability_blame(db, err.cmt.immutability_blame());
}
err_out_of_scope(super_scope, sub_scope, cause) => {
let (value_kind, value_msg) = match err.cmt.cat {
mc::Categorization::Rvalue(..) =>
("temporary value", "temporary value created here"),
_ =>
("borrowed value", "borrow occurs here")
};
let is_closure = match cause {
euv::ClosureCapture(s) => {
// The primary span starts out as the closure creation point.
// Change the primary span here to highlight the use of the variable
// in the closure, because it seems more natural. Highlight
// closure creation point as a secondary span.
match db.span.primary_span() {
Some(primary) => {
db.span = MultiSpan::from_span(s);
db.span_label(primary, "capture occurs here");
db.span_label(s, "does not live long enough");
true
}
None => false
}
}
_ => {
db.span_label(error_span, "does not live long enough");
false
}
};
let sub_span = self.region_end_span(sub_scope);
let super_span = self.region_end_span(super_scope);
match (sub_span, super_span) {
(Some(s1), Some(s2)) if s1 == s2 => {
if !is_closure {
db.span = MultiSpan::from_span(s1);
db.span_label(error_span, value_msg);
let msg = match opt_loan_path(&err.cmt) {
None => value_kind.to_string(),
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
};
db.span_label(s1,
format!("{} dropped here while still borrowed", msg));
} else {
db.span_label(s1, format!("{} dropped before borrower", value_kind));
}
db.note("values in a scope are dropped in the opposite order \
they are created");
}
(Some(s1), Some(s2)) if !is_closure => {
db.span = MultiSpan::from_span(s2);
db.span_label(error_span, value_msg);
let msg = match opt_loan_path(&err.cmt) {
None => value_kind.to_string(),
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
};
db.span_label(s2, format!("{} dropped here while still borrowed", msg));
db.span_label(s1, format!("{} needs to live until here", value_kind));
}
_ => {
match sub_span {
Some(s) => {
db.span_label(s, format!("{} needs to live until here",
value_kind));
}
None => {
self.tcx.note_and_explain_region(
db,
"borrowed value must be valid for ",
sub_scope,
"...");
}
}
match super_span {
Some(s) => {
db.span_label(s, format!("{} only lives until here", value_kind));
}
None => {
self.tcx.note_and_explain_region(
db,
"...but borrowed value is only valid for ",
super_scope,
"");
}
}
}
}
if let Some(_) = statement_scope_span(self.tcx, super_scope) {
db.note("consider using a `let` binding to increase its lifetime");
}
}
err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
let descr = match opt_loan_path(&err.cmt) {
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&lp))
}
None => self.cmt_to_string(&err.cmt),
};
self.tcx.note_and_explain_region(
db,
&format!("{} would have to be valid for ",
descr),
loan_scope,
"...");
self.tcx.note_and_explain_region(
db,
&format!("...but {} is only valid for ", descr),
ptr_scope,
"");
}
}
}
fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'tcx>,
error_span: &Span) {
match err.cmt.note {