I want to implement the From
trait for an enum.
It's OK for usize
, but fail for function type.
Is there any difference between usize and function type?
The code:
type Foo = fn (usize) -> usize;
enum Value {
Number(usize),
Function(Foo),
}
impl From<usize> for Value {
fn from(n: usize) -> Self {
Value::Number(n)
}
}
impl From<Foo> for Value {
fn from(f: Foo) -> Self {
Value::Function(f)
}
}
fn main() {
let n: usize = 123;
let vn: Value = n.into(); // OK for usize
fn testf(n: usize) -> usize { n * n }
let vf: Value = testf.into(); // fail for Foo
}
The error:
error[E0277]: the trait bound `Value: From<fn(usize) -> usize {testf}>` is not satisfied
--> t.rs:24:27
|
24 | let vf: Value = testf.into(); // fail for Foo
| ^^^^ the trait `From<fn(usize) -> usize {testf}>` is not implemented for `Value`
|
= help: the following implementations were found:
<Value as From<fn(usize) -> usize>>
<Value as From<usize>>
= note: required because of the requirements on the impl of `Into<Value>` for `fn(usize) -> usize {testf}`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
The error says that From<fn(usize) -> usize {testf}>
is needed but only has From<fn(usize) -> usize>
. I think the problem is {testf}
, but I do not know why.
Thanks in advance
CodePudding user response:
In Rust, function definitions does not have the fn
type. They have a distinct, unnameable type that the compiler spells out as signature {name}
, e.g. fn(usize) -> usize {testf}
.
This type can be coerced, i.e. converted, to the corresponding fn
type (fn(usize) -> usize
), and usually it does so automatically, but when working with generics it does not.
You can force the compiler to coerce with as
:
fn testf(n: usize) -> usize { n * n }
let vf: Value = (testf as fn(usize) -> usize).into();
Or by specifying the type explicitly:
fn testf(n: usize) -> usize { n * n }
let testf_fn: fn(usize) -> usize = testf;
let vf: Value = testf_fn.into();