use diagnostic-mutating style for note_type_err too

that is much cleaner than the `type_err!` style I used earlier.
This commit is contained in:
Ariel Ben-Yehuda 2016-07-21 20:12:30 +03:00 committed by Ariel Ben-Yehuda
parent 1e4f6d5683
commit 93a96835b0
4 changed files with 53 additions and 55 deletions

View File

@ -521,25 +521,25 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn report_and_explain_type_error_with_code(&self,
origin: TypeOrigin,
values: Option<ValuePairs<'tcx>>,
terr: &TypeError<'tcx>,
message: &str,
code: &str)
-> DiagnosticBuilder<'tcx>
pub fn note_type_err(&self,
diag: &mut DiagnosticBuilder<'tcx>,
origin: TypeOrigin,
values: Option<ValuePairs<'tcx>>,
terr: &TypeError<'tcx>)
{
let expected_found = match values {
None => None,
Some(values) => match self.values_str(&values) {
Some((expected, found)) => Some((expected, found)),
None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
None => {
// Derived error. Cancel the emitter.
self.tcx.sess.diagnostic().cancel(diag);
return
}
}
};
let span = origin.span();
let mut err = self.tcx.sess.struct_span_err_with_code(
span, message, code);
let mut is_simple_error = false;
@ -551,21 +551,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
};
if !is_simple_error || check_old_school() {
err.note_expected_found(&"type", &expected, &found);
diag.note_expected_found(&"type", &expected, &found);
}
}
if !is_simple_error && check_old_school() {
err.span_note(span, &format!("{}", terr));
diag.span_note(span, &format!("{}", terr));
} else {
err.span_label(span, &terr);
diag.span_label(span, &terr);
}
self.note_error_origin(&mut err, &origin);
self.check_and_note_conflicting_crates(&mut err, terr, span);
self.tcx.note_and_explain_type_err(&mut err, terr, span);
err
self.note_error_origin(diag, &origin);
self.check_and_note_conflicting_crates(diag, terr, span);
self.tcx.note_and_explain_type_err(diag, terr, span);
}
pub fn report_and_explain_type_error(&self,
@ -574,8 +572,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-> DiagnosticBuilder<'tcx>
{
// FIXME: do we want to use a different error code for each origin?
let failure_str = trace.origin.as_failure_str();
type_err!(self, trace.origin, Some(trace.values), terr, E0308, "{}", failure_str)
let mut diag = struct_span_err!(
self.tcx.sess, trace.origin.span(), E0308,
"{}", trace.origin.as_failure_str()
);
self.note_type_err(&mut diag, trace.origin, Some(trace.values), terr);
diag
}
/// Returns a string of the form "expected `{}`, found `{}`".

View File

@ -59,16 +59,3 @@ macro_rules! span_bug {
$crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*))
})
}
#[macro_export]
macro_rules! type_err {
($infcx:expr, $origin: expr, $values: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
__diagnostic_used!($code);
$infcx.report_and_explain_type_error_with_code(
$origin,
$values,
&$terr,
&format!($($message)*),
stringify!($code))
})
}

View File

@ -157,14 +157,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
}
let mut diag = type_err!(
self,
origin,
values,
err,
E0271,
"type mismatch resolving `{}`",
predicate);
let mut diag = struct_span_err!(
self.tcx.sess, origin.span(), E0271,
"type mismatch resolving `{}`", predicate
);
self.note_type_err(&mut diag, origin, values, err);
self.note_obligation_cause(&mut diag, obligation);
diag.emit();
});

View File

@ -325,13 +325,19 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
impl_fty,
trait_fty);
let values = Some(infer::ValuePairs::Types(ExpectedFound {
expected: trait_fty,
found: impl_fty
}));
type_err!(infcx, origin, values, terr, E0053,
"method `{}` has an incompatible type for trait",
trait_m.name).emit();
let mut diag = struct_span_err!(
tcx.sess, origin.span(), E0053,
"method `{}` has an incompatible type for trait", trait_m.name
);
infcx.note_type_err(
&mut diag, origin,
Some(infer::ValuePairs::Types(ExpectedFound {
expected: trait_fty,
found: impl_fty
})), &terr
);
diag.emit();
return
}
@ -476,13 +482,19 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
impl_ty,
trait_ty);
let values = Some(infer::ValuePairs::Types(ExpectedFound {
expected: trait_ty,
found: impl_ty
}));
type_err!(infcx, origin, values, terr, E0326,
"implemented const `{}` has an incompatible type for \
trait", trait_c.name).emit();
let mut diag = struct_span_err!(
tcx.sess, origin.span(), E0326,
"implemented const `{}` has an incompatible type for trait",
trait_c.name
);
infcx.note_type_err(
&mut diag, origin,
Some(infer::ValuePairs::Types(ExpectedFound {
expected: trait_ty,
found: impl_ty
})), &terr
);
diag.emit();
}
});
}