use new note_expected_found API

This API pulls the "expected type foo, found type bar" out after the
main snippet. There are some other places where it makes sense, but this
is a start.
This commit is contained in:
Niko Matsakis 2016-04-20 15:00:05 -04:00
parent 11dc974a38
commit d9a947ce8f
6 changed files with 46 additions and 49 deletions

View file

@ -249,12 +249,12 @@ pub trait ErrorReporting<'tcx> {
terr: &TypeError<'tcx>)
-> DiagnosticBuilder<'tcx>;
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)>;
fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
&self,
exp_found: &ty::error::ExpectedFound<T>)
-> Option<String>;
-> Option<(String, String)>;
fn report_concrete_failure(&self,
origin: SubregionOrigin<'tcx>,
@ -535,7 +535,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
trace: TypeTrace<'tcx>,
terr: &TypeError<'tcx>)
-> DiagnosticBuilder<'tcx> {
let expected_found_str = match self.values_str(&trace.values) {
let (expected, found) = match self.values_str(&trace.values) {
Some(v) => v,
None => {
return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
@ -548,18 +548,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
false
};
let expected_found_str = if is_simple_error {
expected_found_str
} else {
format!("{} ({})", expected_found_str, terr)
};
let mut err = struct_span_err!(self.tcx.sess,
trace.origin.span(),
E0308,
"{}: {}",
trace.origin,
expected_found_str);
"{}",
trace.origin);
if !is_simple_error {
err = err.note_expected_found(&"type", &expected, &found);
}
err = err.span_label(trace.origin.span(), &terr);
self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
@ -574,6 +573,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
},
_ => ()
}
err
}
@ -631,7 +631,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
/// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
/// error.
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> {
match *values {
infer::Types(ref exp_found) => self.expected_found_str(exp_found),
infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
@ -642,7 +642,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
&self,
exp_found: &ty::error::ExpectedFound<T>)
-> Option<String>
-> Option<(String, String)>
{
let expected = exp_found.expected.resolve(self);
if expected.references_error() {
@ -654,9 +654,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
return None;
}
Some(format!("expected `{}`, found `{}`",
expected,
found))
Some((format!("{}", expected), format!("{}", found)))
}
fn report_generic_bound_failure(&self,
@ -1751,11 +1749,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
};
match self.values_str(&trace.values) {
Some(values_str) => {
Some((expected, found)) => {
err.span_note(
trace.origin.span(),
&format!("...so that {} ({})",
desc, values_str));
&format!("...so that {} (expected {}, found {})",
desc, expected, found));
}
None => {
// Really should avoid printing this error at

View file

@ -116,8 +116,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
// Check that the types of the end-points can be unified.
let types_unify = require_same_types(
tcx, Some(fcx.infcx()), false, pat.span, rhs_ty, lhs_ty,
|| "mismatched types in range".to_string()
tcx, Some(fcx.infcx()), false, pat.span, rhs_ty, lhs_ty,
"mismatched types in range",
);
// It's ok to return without a message as `require_same_types` prints an error.

View file

@ -61,10 +61,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &TyCtxt<'tcx>, it: &hir::ForeignItem,
it.span,
i_ty.ty,
fty,
|| {
format!("intrinsic has wrong type: expected `{}`",
fty)
});
"intrinsic has wrong type");
}
}

View file

@ -418,8 +418,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
let _ = ::require_same_types(
fcx.tcx(), Some(fcx.infcx()), false, span,
sig.inputs[0], rcvr_ty,
|| "mismatched method receiver".to_owned()
);
"mismatched method receiver");
}
fn check_variances_for_type_defn(&self,

View file

@ -1044,8 +1044,9 @@ fn convert_enum_def<'tcx>(tcx: &TyCtxt<'tcx>,
-> ty::AdtDefMaster<'tcx>
{
fn print_err(tcx: &TyCtxt, span: Span, ty: ty::Ty, cv: ConstVal) {
span_err!(tcx.sess, span, E0079, "mismatched types: expected `{}` got `{}`",
ty, cv.description());
struct_span_err!(tcx.sess, span, E0079, "mismatched types")
.note_expected_found(&"type", &ty, &format!("{}", cv.description()))
.emit();
}
fn evaluate_disr_expr<'tcx>(tcx: &TyCtxt<'tcx>,
repr_ty: attr::IntType,

View file

@ -185,15 +185,14 @@ fn require_c_abi_if_variadic(tcx: &TyCtxt,
}
}
fn require_same_types<'a, 'tcx, M>(tcx: &TyCtxt<'tcx>,
maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
t1_is_expected: bool,
span: Span,
t1: Ty<'tcx>,
t2: Ty<'tcx>,
msg: M)
-> bool where
M: FnOnce() -> String,
fn require_same_types<'a, 'tcx>(tcx: &TyCtxt<'tcx>,
maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
t1_is_expected: bool,
span: Span,
t1: Ty<'tcx>,
t2: Ty<'tcx>,
msg: &str)
-> bool
{
let result = match maybe_infcx {
None => {
@ -208,7 +207,17 @@ fn require_same_types<'a, 'tcx, M>(tcx: &TyCtxt<'tcx>,
match result {
Ok(_) => true,
Err(ref terr) => {
let mut err = struct_span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
err = err.span_label(span, &terr);
let (mut expected_ty, mut found_ty) =
if t1_is_expected {(t1, t2)} else {(t2, t1)};
if let Some(infcx) = maybe_infcx {
expected_ty = infcx.resolve_type_vars_if_possible(&expected_ty);
found_ty = infcx.resolve_type_vars_if_possible(&found_ty);
}
err = err.note_expected_found(&"type",
&expected_ty,
&found_ty);
tcx.note_and_explain_type_err(&mut err, terr, span);
err.emit();
false
@ -250,10 +259,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
});
require_same_types(tcx, None, false, main_span, main_t, se_ty,
|| {
format!("main function expects type: `{}`",
se_ty)
});
"main function has wrong type");
}
_ => {
span_bug!(main_span,
@ -301,11 +307,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
});
require_same_types(tcx, None, false, start_span, start_t, se_ty,
|| {
format!("start function expects type: `{}`",
se_ty)
});
"start function has wrong type");
}
_ => {
span_bug!(start_span,