# Implementing traits for function types

**URL:** <https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888>\
**Category:** language design\
**Created:** [September 10, 2017, 8:38pm UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888 "2017-09-10T20:38:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jplatte](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jplatte/32/11437_2.png) [@jplatte](https://internals.rust-lang.org/u/jplatte)\
**Post date:** [September 10, 2017, 8:38pm UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/1 "2017-09-10T20:38:24Z")

</div>

I haven’t been able to find any documentation of how trait resolution is supposed to work for functions. The current state in the compiler seems to be that the unique type of a function is not coerced to its `fn(args...) -> retval` form. So if I have

```rust
impl Foo for fn(Bar) -> u32 {
    fn foo(self) { ... }
}

fn baz(bar: Bar) -> u32 {
    ...
}

```

This works:

```rust
Foo::foo(baz as fn(Bar) -> u32);

```

but this doesn’t:

```rust
Foo::foo(baz);

```

Is this a deliberate feature or has it just not been considered before?

My concrete use case is this: [https://play.rust-lang.org/?gist=cad50431d1662d8bf8692c7f17f7f3e7](https://play.rust-lang.org/?gist=cad50431d1662d8bf8692c7f17f7f3e7), which AFAICT could be used to implement [a requested feature for serde](https://github.com/serde-rs/serde/issues/368) in a very neat, backwards-compatible way.

---

<div class="post-metadata">

**Author:** ![leodasvacas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leodasvacas/32/4060_2.png) [@leodasvacas](https://internals.rust-lang.org/u/leodasvacas)\
**Post date:** [September 10, 2017, 10:37pm UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/2 "2017-09-10T22:37:05Z")

</div>

The unique type of a function is coercible to the corresponding fn pointer. But coercions are not performed to match generic bounds. What you want is [this](https://play.rust-lang.org/?gist=20a3e49fb3026416abb517595baceff6&version=nightly), but it results in conflicting implementations. There is an idea for solving this in the far future called intersection impls. So if the cast is not acceptable, you’ll have to find some other design that solves your problem.

---

<div class="post-metadata">

**Author:** ![jplatte](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jplatte/32/11437_2.png) [@jplatte](https://internals.rust-lang.org/u/jplatte)\
**Post date:** [September 11, 2017, 5:03am UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/3 "2017-09-11T05:03:06Z")

</div>

> [@leodasvacas](#):
>
> What you want is this, but it results in conflicting implementations.

I know, I tried that already. It would also be interesting to know if there is a possibility for those two `impl`s not to be considered conflicting in a future version of specialization, but I haven't looked into the details of that yet.

> [@leodasvacas](#):
>
> But coercions are not performed to match generic bounds.

Yeah, but why not, in this case? You can't implement traits for a unique function type, and even if you could I don't really see why you'd want to, so why doesn't trait resolution consider the regular fn type?

---

<div class="post-metadata">

**Author:** ![aepsil0n](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aepsil0n/32/324_2.png) [@aepsil0n](https://internals.rust-lang.org/u/aepsil0n)\
**Post date:** [September 11, 2017, 11:57am UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/4 "2017-09-11T11:57:12Z")

</div>

> [@jplatte](#):
>
> Yeah, but why not, in this case? You can’t implement traits for a unique function type, and even if you could I don’t really see why you’d want to, so why doesn’t trait resolution consider the regular fn type?

Say, you'd have another blanket `impl<T> Foo for T` and your other impl could not apply any more. Not saying that this is a particularly sensible thing to do in your case, but the general rules must be able to handle that appropriately. I could imagine people doing specializations on trait objects or function pointers for optimization purposes, because they have different run-time characteristics.

---

<div class="post-metadata">

**Author:** ![leodasvacas](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leodasvacas/32/4060_2.png) [@leodasvacas](https://internals.rust-lang.org/u/leodasvacas)\
**Post date:** [September 11, 2017, 1:05pm UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/5 "2017-09-11T13:05:50Z")

</div>

> Yeah, but why not, in this case? You can’t implement traits for a unique function type, and even if you could I don’t really see why you’d want to, so why doesn’t trait resolution consider the regular fn type?

You make a good point but see [here](https://play.rust-lang.org/?gist=2903dc272c195bd8a5eab92c39fb5efa&version=nightly) an API evolution that is backwards compatible today but would be backwards incompatible if the coercion happened.

---

<div class="post-metadata">

**Author:** ![jplatte](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jplatte/32/11437_2.png) [@jplatte](https://internals.rust-lang.org/u/jplatte)\
**Post date:** [September 11, 2017, 1:48pm UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/6 "2017-09-11T13:48:04Z")

</div>

There are a lot of cases where a new version of Rust has changed things in a theoretically-backwards-incompatible way, as long as those changes didn’t have a noticable practical impact. Even adding a function `fn1` to a trait `T1` is a backwards-incompatible change, because if a type `Foo` that implements `T1` also implements another trait `T2` with a function `fn1`, `Foo::fn1(...)` becomes ambiguous.

So I’m pretty sure that backwards-compatiblity shouldn’t be a big concern here.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:28am UTC](https://internals.rust-lang.org/t/implementing-traits-for-function-types/5888/7 "2019-03-25T08:28:59Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
