Provide context on E0308 involving fn items
This commit is contained in:
parent
a39c7787ba
commit
f84b7e1b05
@ -1256,7 +1256,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
(ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
|
||||
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
|
||||
let mut values = self.cmp_fn_sig(&sig1, sig2);
|
||||
values.0.push_normal(format!(
|
||||
values.0.push_highlighted(format!(
|
||||
" {{{}}}",
|
||||
self.tcx.def_path_str_with_substs(*did1, substs1)
|
||||
));
|
||||
|
@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||
self.suggest_missing_await(err, expr, expected, expr_ty);
|
||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||
}
|
||||
|
||||
// Requires that the two types unify, and prints an error message if
|
||||
|
@ -5496,6 +5496,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn note_need_for_fn_pointer(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) {
|
||||
match (&expected.kind, &found.kind) {
|
||||
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
|
||||
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
|
||||
let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
|
||||
if sig1 != sig2 {
|
||||
return;
|
||||
}
|
||||
err.note(
|
||||
"different `fn` items always have unique types, even if their signatures are \
|
||||
the same",
|
||||
);
|
||||
err.help(&format!("change the expectation to require function pointer `{}`", sig1));
|
||||
err.help(&format!(
|
||||
"if the expectation is due to type inference, cast the expected `fn` to a \
|
||||
function pointer: `{} as {}`",
|
||||
self.tcx.def_path_str_with_substs(*did1, substs1),
|
||||
sig1
|
||||
));
|
||||
}
|
||||
(ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
|
||||
let sig1 = self.tcx.fn_sig(*did).subst(self.tcx, substs);
|
||||
if sig1 != *sig2 {
|
||||
return;
|
||||
}
|
||||
err.help(&format!("change the expectation to require function pointer `{}`", sig1));
|
||||
err.help(&format!(
|
||||
"if the expectation is due to type inference, cast the expected `fn` to a \
|
||||
function pointer: `{} as {}`",
|
||||
self.tcx.def_path_str_with_substs(*did, substs),
|
||||
sig1
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// A common error is to add an extra semicolon:
|
||||
///
|
||||
/// ```
|
||||
|
@ -12,22 +12,44 @@ impl<T> Foo for T { /* `foo` is still default here */ }
|
||||
fn main() {
|
||||
eq(foo::<u8>, bar::<u8>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
//~| found fn item `fn(_) -> _ {bar::<u8>}`
|
||||
//~| expected fn item, found a different fn item
|
||||
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
//~| found fn item `fn(_) -> _ {bar::<u8>}`
|
||||
//~| expected fn item, found a different fn item
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expectation to require function pointer
|
||||
//~| if the expectation is due to type inference, cast the expected `fn` to a function pointer
|
||||
|
||||
eq(foo::<u8>, foo::<i8>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `u8`, found `i8`
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expectation to require function pointer
|
||||
//~| if the expectation is due to type inference, cast the expected `fn` to a function pointer
|
||||
|
||||
eq(bar::<String>, bar::<Vec<u8>>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
||||
//~| found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
|
||||
//~| expected struct `std::string::String`, found struct `std::vec::Vec`
|
||||
//~| expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
||||
//~| found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
|
||||
//~| expected struct `std::string::String`, found struct `std::vec::Vec`
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expectation to require function pointer
|
||||
//~| if the expectation is due to type inference, cast the expected `fn` to a function pointer
|
||||
|
||||
// Make sure we distinguish between trait methods correctly.
|
||||
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `u8`, found `u16`
|
||||
//~| different `fn` items always have unique types, even if their signatures are the same
|
||||
//~| change the expectation to require function pointer
|
||||
//~| if the expectation is due to type inference, cast the expected `fn` to a function pointer
|
||||
|
||||
eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
//~| found fn pointer `fn(_) -> _`
|
||||
//~| expected fn item, found fn pointer
|
||||
//~| change the expectation to require function pointer
|
||||
//~| if the expectation is due to type inference, cast the expected `fn` to a function pointer
|
||||
|
||||
eq(foo::<u8> as fn(isize) -> isize, bar::<u8>); // ok!
|
||||
}
|
||||
|
@ -6,34 +6,57 @@ LL | eq(foo::<u8>, bar::<u8>);
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
found fn item `fn(_) -> _ {bar::<u8>}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expectation to require function pointer `fn(isize) -> isize`
|
||||
= help: if the expectation is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:19:19
|
||||
--> $DIR/fn-item-type.rs:22:19
|
||||
|
|
||||
LL | eq(foo::<u8>, foo::<i8>);
|
||||
| ^^^^^^^^^ expected `u8`, found `i8`
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
found fn item `fn(_) -> _ {foo::<i8>}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expectation to require function pointer `fn(isize) -> isize`
|
||||
= help: if the expectation is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:23:23
|
||||
--> $DIR/fn-item-type.rs:29:23
|
||||
|
|
||||
LL | eq(bar::<String>, bar::<Vec<u8>>);
|
||||
| ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec`
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
||||
found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expectation to require function pointer `fn(isize) -> isize`
|
||||
= help: if the expectation is due to type inference, cast the expected `fn` to a function pointer: `bar::<std::string::String> as fn(isize) -> isize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:30:26
|
||||
--> $DIR/fn-item-type.rs:39:26
|
||||
|
|
||||
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
|
||||
|
|
||||
= note: expected fn item `fn() {<u8 as Foo>::foo}`
|
||||
found fn item `fn() {<u16 as Foo>::foo}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expectation to require function pointer `fn()`
|
||||
= help: if the expectation is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/fn-item-type.rs:46:19
|
||||
|
|
||||
LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
|
||||
|
|
||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||
found fn pointer `fn(_) -> _`
|
||||
= help: change the expectation to require function pointer `fn(isize) -> isize`
|
||||
= help: if the expectation is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user