Problems implementing traits for functions

I've found a weird edge case (?) in implementing traits for functions (that is fn, function pointers). I've created a minimal example here: Rust Playground. The following code doesn't compile:

pub trait MyTrait {
    type Argument;
    type Result;
    fn call(&mut self, arg: Self::Argument) -> Self::Result;
}

impl<Arg, R> MyTrait for fn(Arg) -> R {
    type Argument = Arg;
    type Result = R;
    fn call(&mut self, arg: Self::Argument) -> Self::Result {
        (self)(arg)
    }
}

fn main() {
    direct(convert(fn1));
    // This won't compile?
    // However the "convert" function just returns its argument.
    direct(fn1);

    println!("Ok");
}

fn fn1(_: ()) -> usize { 1 }

fn convert<Arg, R>(f: fn(Arg) -> R) -> impl MyTrait<Argument = Arg, Result = R> {
    f
}

fn direct<T: MyTrait>(_f: T) { }

Am I missing something or is this a bug? Any help would be appreciated, thank you.

fn1, as written, isn't an fn pointer, it's an "fn item" - that is, it's a reference to that specific function. You need to cast it to be an fn pointer, e.g.:

direct(fn1 as fn(_) -> _);

It will, however, coerce, to a fn pointer, which is why it works via convert.

I didn't know there were also fn items. Is there any way I can pass fn1 directly to direct, without casting it or calling it indirectly via convert?

Or can I change the impl MyTrait for fn(Arg) -> R to work with fn1 directly? I know of the Fn and related trait, but those won't work in the actual code I'm working with.

Perhaps you can just impl MyTrait for a closure, i.e.:

impl<F, R> MyTrait for F where F: FnMut(()) -> R {
    type Argument = ();
    type Result = R;
    
    fn call(&mut self, _: Self::Argument) -> Self::Result {
        (self)(())
    }
}

Then drop convert() and just use direct().

If you change Argument to a parameter type instead of an associated type, you can do this:

pub trait MyTrait<Argument> {
    type Result;
    fn call(&mut self, arg: Argument) -> Self::Result;
}

impl<Arg, R, F> MyTrait<Arg> for F where F: Fn(Arg) -> R {
    type Result = R;
    fn call(&mut self, arg: Arg) -> Self::Result {
        (self)(arg)
    }
}

fn main() {
    direct(fn1);
    println!("Ok");
}

fn fn1(_: ()) -> usize { 1 }

fn direct<U, T: MyTrait<U>>(_f: T) { }

Playground

Unfortunately this won't work for generic arguments.

I really only need a single implementation of my trait per type, so I don't think this will work.

I want to thank everybody one last time for all the replies. I decided to go with letting the users convert the function items into pointer (i.e. `my_fn as fn(_) -> _) themselves as @vitalyd suggested.

I do think it's to bad that Into doesn't include this coercion because that would fix all my problems by changing the generic bound to T: Into<MyTrait>.