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.
|
// The algorithm here is inspired by levenshtein distance and longest common subsequence.
|
||||||
// We'll try to detect 4 different types of mistakes:
|
// 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
|
// - 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,
|
// A tuple wrap suggestion actually occurs within,
|
||||||
// so don't do anything special here.
|
// so don't do anything special here.
|
||||||
err = self.err_ctxt().report_and_explain_type_error(
|
err = self.err_ctxt().report_and_explain_type_error(
|
||||||
TypeTrace::types(
|
mk_trace(
|
||||||
&self.misc(*lo),
|
*lo,
|
||||||
true,
|
formal_and_expected_inputs[mismatch_idx.into()],
|
||||||
formal_and_expected_inputs[mismatch_idx.into()].1,
|
|
||||||
provided_arg_tys[mismatch_idx.into()].0,
|
provided_arg_tys[mismatch_idx.into()].0,
|
||||||
),
|
),
|
||||||
terr,
|
terr,
|
||||||
@ -748,9 +759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
errors.drain_filter(|error| {
|
errors.drain_filter(|error| {
|
||||||
let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
|
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 (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
|
||||||
let (expected_ty, _) = formal_and_expected_inputs[*expected_idx];
|
let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
|
||||||
let cause = &self.misc(provided_span);
|
|
||||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
|
||||||
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
|
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
|
||||||
self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
|
self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
|
||||||
return true;
|
return true;
|
||||||
@ -774,8 +783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
{
|
{
|
||||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
|
let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx];
|
||||||
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
|
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
|
||||||
let cause = &self.misc(provided_arg_span);
|
let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty);
|
||||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
|
||||||
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
|
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
|
||||||
self.emit_coerce_suggestions(
|
self.emit_coerce_suggestions(
|
||||||
&mut err,
|
&mut err,
|
||||||
@ -847,8 +855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
|
let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx];
|
||||||
let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
|
let (provided_ty, provided_span) = provided_arg_tys[provided_idx];
|
||||||
if let Compatibility::Incompatible(error) = compatibility {
|
if let Compatibility::Incompatible(error) = compatibility {
|
||||||
let cause = &self.misc(provided_span);
|
let trace = mk_trace(provided_span, (formal_ty, expected_ty), provided_ty);
|
||||||
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
|
|
||||||
if let Some(e) = error {
|
if let Some(e) = error {
|
||||||
self.err_ctxt().note_type_err(
|
self.err_ctxt().note_type_err(
|
||||||
&mut 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