Open gnzlbg opened 5 years ago
This is expected, since u0
doesn't have type fn(f32) -> f32
, since every function item gets its own anonymous type (like closures). These types will coerce to the corresponding function pointer type (fn(f32) -> f32
here), but that coercion only kicks in when there's a known expected type to coerce to.
Ah! So that's what's the {main::u0}
in the fn(f32) -> f32 {main::u0}
is!
I think this error could use a note, explaining that the fn(f32) -> f32 {main::u0}
is an anonymous type, different from fn(f32) -> f32
, but that it can be coerced into fn(f32) -> f32
, although this coercions are not triggering here.
Maybe suggest using .. as fn(f32) -> f32
here to trigger the coercion.
cc @estebank
struct Dummy;
impl From<fn(u32) -> String> for Dummy {
fn from(_: fn(u32) -> String) -> Self { unimplemented!() }
}
fn foo(_: u32) -> String { unimplemented!() }
fn main() {
Dummy::from(foo);
}
we currently emit
error[E0277]: the trait bound `Dummy: std::convert::From<fn(u32) -> std::string::String {foo}>` is not satisfied
--> src/main.rs:10:5
|
10 | Dummy::from(foo);
| ^^^^^^^^^^^ the trait `std::convert::From<fn(u32) -> std::string::String {foo}>` is not implemented for `Dummy`
|
= help: the following implementations were found:
<Dummy as std::convert::From<fn(u32) -> std::string::String>>
= note: required by `std::convert::From::from`
The solution is changing the call to Dummy::from(foo as fn(u32) -> String);
.
I know this issue is about improving the diagnostic, but it seemed as good a place as any to note that fixing this is desirable, but apparently there are a number of implementation challenges, according to @nikomatsakis (Zulip source).
https://github.com/rust-lang/rust/issues/62621#issuecomment-510867961 suggested that the next step might be an RFC, but it sounds like the more pressing issue is sorting through some of the implementation challenges.
Current output:
Only change to the path of the fn
item
error[E0277]: the trait bound `f32: Call<fn(f32) -> f32 {u0}>` is not satisfied
--> src/main.rs:23:26
|
23 | let _ = (0_f32).call(u0);
| ---- ^^ the trait `Call<fn(f32) -> f32 {u0}>` is not implemented for `f32`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Call<F>`:
<f32 as Call<fn(f32) -> i32>>
<f32 as Call<fn(f32) -> f32>>
Much better output for this case
error[E0277]: the trait bound `Dummy: From<fn(u32) -> String {foo}>` is not satisfied
--> src/main.rs:10:5
|
10 | Dummy::from(foo);
| ^^^^^ the trait `From<fn(u32) -> String {foo}>` is not implemented for `Dummy`
|
= help: the trait `From<fn(u32) -> String>` is implemented for `Dummy`
= help: for that trait implementation, expected `fn(u32) -> String`, found `fn(u32) -> String {foo}`
We need to explicitly check for this case and detect fn(u32) -> String { foo }
can be cast to fn(u32) -> String
and provide a structured suggestion to do so for both cases presented.
This works (Playground):
but this fails (Playground):
with
I'm not sure if this is by design or not (AFAICT the trait bound is satisfied - EDIT: it is by design, see below), but the error message could be at least much clearer.