How to implement trait for fn


#1
trait Handler {
    fn handle(&mut self);
}

impl Handler for fn() {
    fn handle(&mut self) {
    }
}

fn foo() {
}

#[test]
fn it_works() {
    let f: Box<Handler> = Box::new(foo);
}

It says

src/lib.rs:15:27: 15:40 error: the trait `Handler` is not implemented for the type `fn() {foo}` [E0277]
src/lib.rs:15     let f: Box<Handler> = Box::new(foo);
                                        ^~~~~~~~~~~~~
src/lib.rs:15:27: 15:40 help: run `rustc --explain E0277` to see a detailed explanation
src/lib.rs:15:27: 15:40 help: the following implementations were found:
src/lib.rs:15:27: 15:40 help:   <fn() as Handler>
src/lib.rs:15:27: 15:40 note: required for the cast to the object type `Handler`
error: aborting due to previous error

#2
trait Handler {
    fn handle(&mut self);
}

impl Handler for fn() {
    fn handle(&mut self) {
    }
}

fn foo() {
}

#[test]
fn no_but_this_does() {
    let f: Box<Handler> = Box::new(foo as fn());
}

Note the type in the error is fn() {foo} (a function item type) not fn() (a function pointer type).


#3

I don’t get it. Could you please explain or provide some link with information?


#4

The type of foo is not fn(), it is fn() {foo}; a type that is specific to that one function. The type of no_but_this_does is not fn(), but fn() {no_but_this_does}. Both of these will coerce to the simpler fn() type, if the compiler is forced to do so.

You implemented the trait on the function pointer type fn(), not on the infinite number of function item types, so you have to force the compiler to convert the function items into function pointers, which is what the as fn() does.

It’s very roughly like how [u8; 10] and [u8; 15] are both a kind of u8 array, but aren’t exactly the same as [u8].

There’s a bit about this in the reference section on function types for specific items. A quick poke through the book doesn’t reveal anything pertinent.


#5

Thanks.