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:
parent
11dc974a38
commit
d9a947ce8f
6 changed files with 46 additions and 49 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue