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)) => {
|
(ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
|
||||||
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
|
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
|
||||||
let mut values = self.cmp_fn_sig(&sig1, sig2);
|
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)
|
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_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||||
self.suggest_missing_await(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
|
// 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:
|
/// A common error is to add an extra semicolon:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -15,19 +15,41 @@ fn main() {
|
|||||||
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
|
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||||
//~| found fn item `fn(_) -> _ {bar::<u8>}`
|
//~| found fn item `fn(_) -> _ {bar::<u8>}`
|
||||||
//~| expected fn item, found a different fn item
|
//~| 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>);
|
eq(foo::<u8>, foo::<i8>);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `u8`, found `i8`
|
//~| 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>>);
|
eq(bar::<String>, bar::<Vec<u8>>);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
//~| expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
||||||
//~| found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
|
//~| found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
|
||||||
//~| expected struct `std::string::String`, found struct `std::vec::Vec`
|
//~| 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.
|
// Make sure we distinguish between trait methods correctly.
|
||||||
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `u8`, found `u16`
|
//~| 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>}`
|
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||||
found fn item `fn(_) -> _ {bar::<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
|
error[E0308]: mismatched types
|
||||||
--> $DIR/fn-item-type.rs:19:19
|
--> $DIR/fn-item-type.rs:22:19
|
||||||
|
|
|
|
||||||
LL | eq(foo::<u8>, foo::<i8>);
|
LL | eq(foo::<u8>, foo::<i8>);
|
||||||
| ^^^^^^^^^ expected `u8`, found `i8`
|
| ^^^^^^^^^ expected `u8`, found `i8`
|
||||||
|
|
|
|
||||||
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
|
||||||
found fn item `fn(_) -> _ {foo::<i8>}`
|
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
|
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>>);
|
LL | eq(bar::<String>, bar::<Vec<u8>>);
|
||||||
| ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec`
|
| ^^^^^^^^^^^^^^ expected struct `std::string::String`, found struct `std::vec::Vec`
|
||||||
|
|
|
|
||||||
= note: expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
= note: expected fn item `fn(_) -> _ {bar::<std::string::String>}`
|
||||||
found fn item `fn(_) -> _ {bar::<std::vec::Vec<u8>>}`
|
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
|
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);
|
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||||
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
|
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
|
||||||
|
|
|
|
||||||
= note: expected fn item `fn() {<u8 as Foo>::foo}`
|
= note: expected fn item `fn() {<u8 as Foo>::foo}`
|
||||||
found fn item `fn() {<u16 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`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user