mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
More accurately report error when formal and expected signature types differ
This commit is contained in:
parent
312d6b8e9a
commit
55f1f993ff
@ -597,6 +597,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
let mk_trace = |span, (formal_ty, expected_ty), provided_ty| {
|
||||
let mismatched_ty = if expected_ty == provided_ty {
|
||||
// If expected == provided, then we must have failed to sup
|
||||
// the formal type. Avoid printing out "expected Ty, found Ty"
|
||||
// in that case.
|
||||
formal_ty
|
||||
} else {
|
||||
expected_ty
|
||||
};
|
||||
TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty)
|
||||
};
|
||||
|
||||
// The algorithm here is inspired by levenshtein distance and longest common subsequence.
|
||||
// We'll try to detect 4 different types of mistakes:
|
||||
// - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
|
||||
@ -661,10 +673,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// A tuple wrap suggestion actually occurs within,
|
||||
// so don't do anything special here.
|
||||
err = self.err_ctxt().report_and_explain_type_error(
|
||||
TypeTrace::types(
|
||||
&self.misc(*lo),
|
||||
true,
|
||||
formal_and_expected_inputs[mismatch_idx.into()].1,
|
||||
mk_trace(
|
||||
*lo,
|
||||
formal_and_expected_inputs[mismatch_idx.into()],
|
||||
provided_arg_tys[mismatch_idx.into()].0,
|
||||
),
|
||||
terr,
|
||||
@ -748,9 +759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
errors.drain_filter(|error| {
|
||||
let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
|
||||
let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
|
||||
let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
|
||||
let cause = &self.misc(provided_span);
|
||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
||||
let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
|
||||
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
|
||||
self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
|
||||
return true;
|
||||
@ -774,8 +783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
{
|
||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
|
||||
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
|
||||
let cause = &self.misc(provided_arg_span);
|
||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
||||
let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
|
||||
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
|
||||
self.emit_coerce_suggestions(
|
||||
&mut err,
|
||||
@ -847,8 +855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
|
||||
let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
|
||||
if let Compatibility::Incompatible(error) = compatibility {
|
||||
let cause = &self.misc(provided_span);
|
||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
||||
let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
|
||||
if let Some(e) = error {
|
||||
self.err_ctxt().note_type_err(
|
||||
&mut err,
|
||||
|
@ -0,0 +1,25 @@
|
||||
pub trait Foo {
|
||||
type T;
|
||||
}
|
||||
|
||||
impl Foo for i32 {
|
||||
type T = f32;
|
||||
}
|
||||
|
||||
pub struct U<T1, T2>(T1, S<T2>)
|
||||
where
|
||||
T1: Foo<T = T2>;
|
||||
|
||||
pub struct S<T>(T);
|
||||
|
||||
fn main() {
|
||||
// The error message here isn't great -- it has to do with the fact that the
|
||||
// `expected_inputs_for_expected_output` deduced inputs differs from the inputs
|
||||
// that we infer from the constraints of the signature.
|
||||
//
|
||||
// I am not really sure what the best way of presenting this error message is,
|
||||
// since right now it just suggests changing `3u32` <=> `3f32` back and forth.
|
||||
let _: U<_, u32> = U(1, S(3u32));
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/formal-and-expected-differ.rs:22:29
|
||||
|
|
||||
LL | let _: U<_, u32> = U(1, S(3u32));
|
||||
| - ^^^^^^^ expected `f32`, found `u32`
|
||||
| |
|
||||
| arguments to this struct are incorrect
|
||||
|
|
||||
= note: expected struct `S<f32>`
|
||||
found struct `S<u32>`
|
||||
note: tuple struct defined here
|
||||
--> $DIR/formal-and-expected-differ.rs:9:12
|
||||
|
|
||||
LL | pub struct U<T1, T2>(T1, S<T2>)
|
||||
| ^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/formal-and-expected-differ.rs:22:24
|
||||
|
|
||||
LL | let _: U<_, u32> = U(1, S(3u32));
|
||||
| --------- ^^^^^^^^^^^^^ expected `u32`, found `f32`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected struct `U<_, u32>`
|
||||
found struct `U<i32, f32>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user