Implement trait bound for `fn`

Is it possible to implement a trait for a specific function and not all T that implements Fn. Something like this:

trait Function {}

fn a(x: i32) {}
impl Function for fn(i32) {}

fn func<F: Function>(f: F) {}

fn main() {
    func(a);
}

This fails with:

error[E0277]: the trait bound `fn(i32) {a}: Function` is not satisfied
 --> examples/experiment.rs:9:10
  |
9 |     func(a);
  |     ---- ^ the trait `Function` is not implemented for `fn(i32) {a}`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the following implementations were found:
            <fn(i32) as Function>

But trying to do:

impl Function for fn(i32) {a} {}

is also incorrect.

You may want to try a blanket implementation:

trait Function {}
impl<F: Fn(u32)> Function for F {}

Or you may want to use F: Fn(u32) directly.


The issue you're facing is that each function gets its own type, so that when it gets passed into a generic function it can be inlined if necessary.


I just saw that you specified "not for all T which impl Fn" and the issue is that you cannot refer to function types directly. Instead, you could coerce the function into a function pointer with as fn(u32).

1 Like

Any reason why this coercion doesn't happen automatically? I have been using it for some time now, but the ergonomics around it are not great. Constantly needing to re-type function signatures is annoying.

Was this automatic coercion ever considered to be added?

The developers of Rust tend to hang out on the internals forum or Zulip, so it might be better to ask there.

I'm guessing you can't pass a to func() because, while a can be coersed to a fn(i32), places that use generics deliberately don't allow coersions. In particular, I'm referring to this section of the Rust Reference's Type Coersions chapter:

A coercion can only occur at certain coercion sites in a program, these are typically places where the desired type is explicit or can be derived by propagation from explicit types (without type inference).

When a coersion site like a function call uses generics, it's not obvious what type to coerse a into because func() just says it wants some F: Function.

The situation they are trying to avoid is where the user expects one implementation of a trait to be used but actually the compiler has applied an implicit coersion and they get something else. You see this happen in C++ when you mix things like function overloads and subtyping (automatically coersing Child& to Parent&), and it can lead to some subtle gotchas.

1 Like

It does happen automatically in some situations (RFC 401), but trait resolution doesn't fall back to consider coercions.

1 Like

Thanks for the input @Michael-F-Bryan and @quinedot. I have moved the discussion to the internals forum: Extending implicit coercion of function items to function pointers during trait resolution - language design - Rust Internals

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.