# Suggestion: Implement Default for function items

**URL:** <https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875>\
**Category:** Uncategorized\
**Created:** [June 13, 2021, 3:11pm UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875 "2021-06-13T15:11:29Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![DefinitelyNotRobot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/definitelynotrobot/32/8260_2.png) [@DefinitelyNotRobot](https://internals.rust-lang.org/u/DefinitelyNotRobot)\
**Post date:** [June 13, 2021, 3:11pm UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/1 "2021-06-13T15:11:29Z")

</div>

# Problem

It is currently not possible to obtain a function value from its function item type, despite the fact that every function has a unique function item type (note: not to be confused with function pointer type). This should be made possible, since it allows us to compose functions and store the result as function pointers instead of resorting to boxed trait objects.

Example to illustrate (simplified from my actual use-case):

```rust
// We want to "decorate" a function by preprocessing its arguments before calling it, i.e. given 
// some f(x), return a function representing f(g(x)). Afterwards, we want to dynamically dispatch
// the decorated function.

// Version 1:
// Here, we are forced to use `Fn` bound, even though we only want non-closure functions.
fn make_decorated<F: Fn(SomeType)>() -> fn(SomeType) {
    decorated::<F>
}
fn decorated<F: Fn(SomeType)>(x: SomeType) {
    let x = x.changed_version();
    // f(some_arg) // Can't get function item `f` from `F`
}

// Version 2: Forced to use boxed trait object to get around the limitation.
fn make_decorated_2<F: Fn(SomeType)>(f: F) -> Box<dyn Fn(SomeType)> {
    // Forced to use closure
    let decorated = |x: SomeType| {
        let x = x.changed_version();
        f(x)
    };
    Box::new(decorated)
}

// Version 3: Returns impl Fn(SomeType) but not what we want.
fn make_decorated_3<F: Fn(SomeType)>(f: F) -> impl Fn(SomeType) {
    // Forced to use closure
    let decorated = |x: SomeType| {
        let x = x.changed_version();
        f(x)
    };
    decorated
}

```

# Proposal and Alternatives

There are several solutions I can think of.

1. Introduce a new trait `NoEnvFn` which only normal non-closure functions implement, and a corresponding method `NoEnvFn::instance()` to obtain the instance.
2. Implement `Default` for normal functions. In the example above, we can change the required trait bound to `F: Fn() + Default`. This is more general than (1), allowing more than normal functions to be accepted when custom types can implement `Fn` stably, but does not require introducing a new trait. This is the proposal in this thread.

# Complications

I'm not familiar with the internals of the compiler but from what I gathered, `Default` is not a language-item, which might pose issues to the automatically generated function item types.

* * *

The issue here might be niche but we don't want to be forced to pay for what we don't use, sticking to our beloved zero-cost abstraction principle.

What do you think?

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [June 13, 2021, 3:42pm UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/2 "2021-06-13T15:42:07Z")

</div>

Have you seen [Add design notes for function-type `Default` implementation discussion by Diggsey · Pull Request #71 · rust-lang/lang-team · GitHub](https://github.com/rust-lang/lang-team/pull/71)? (there is some additional discussion at [https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20note.20lang-team.2371](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20note.20lang-team.2371))

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [June 13, 2021, 4:02pm UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/3 "2021-06-13T16:02:56Z")

</div>

> [@DefinitelyNotRobot](#):
>
> `// Version 3: Returns impl Fn(SomeType) but not what we want.`

Why isn't this acceptable? Is the problem just that it's hard to store?

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [June 13, 2021, 4:44pm UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/4 "2021-06-13T16:44:16Z")

</div>

FWIW, I ran into a similar situation in a project of my own recently. My workaround was to make a trait with a method that doesn't take `self`, and implement that trait rather than writing free-standing functions. Given any implementor, you can make a second implementor that decorates it – and you can convert the method to a function pointer by specifying the generic parameter.

Making function pointer objects more full-featured would be nice, but this workaround worked well enough for my personal use case.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [June 14, 2021, 12:15am UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/5 "2021-06-14T00:15:46Z")

</div>

There's another fun world where the solution is to lift the `fn()` parameter into a const generic. I think that's the most direct translation of what you're after.

I think what you think you want is fundamentally flawed, though. You say you want to return a decorated `fn()` function pointer, that does _dynamic dispatch_ for the decorated function.

Fundamentally, that doesn't work out. `fn()` has no state (by design), so it statically wraps the decorated function ZST. Think `Decorated<{fn foo}>: Fn()`; you have a distinct instance for each wrapped function.

So either you return some `impl Fn` which has the pointer state to do dynamic dispatch, or you have statically monomorphized decorators which require zero state (just emitted code duplication) and do static dispatch.

But I do agree that there's a fundamental missing piece of vocabulary missing for a "`&dyn Fn()` but thin pointer, no state", or rather, `fn()`, that allows composing wrappers but getting the thin pointer out at the end with unifiable dynamic type. And `impl Fn + Default` does seem to be enough to express it, plus a bit more.

In the mean time, you might try picking out a crate that'll give you `StackBox<dyn Fn()>`. It'll necessarily be a bit bigger than `fn()` would be, but it'll accomplish what you want.

---

<div class="post-metadata">

**Author:** ![DefinitelyNotRobot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/definitelynotrobot/32/8260_2.png) [@DefinitelyNotRobot](https://internals.rust-lang.org/u/DefinitelyNotRobot)\
**Post date:** [June 14, 2021, 1:46am UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/6 "2021-06-14T01:46:00Z")

</div>

> [@bjorn3](#):
>
> Have you seen [Add design notes for function-type `Default` implementation discussion by Diggsey · Pull Request #71 · rust-lang/lang-team · GitHub](https://github.com/rust-lang/lang-team/pull/71)? (there is some additional discussion at [https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20note.20lang-team.2371](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/design.20note.20lang-team.2371))

Thanks for the link. Somehow I didn't encounter this issue on search engines.

> [@scottmcm](#):
>
> Why isn't this acceptable? Is the problem just that it's hard to store?

Imagine if I want to store a collection of different decorated functions which have the same signature. It's not possible to use `impl Fn(SomeType)` in that way directly except for statically dispatching it.

> [@elidupree](#):
>
> FWIW, I ran into a similar situation in a project of my own recently. My workaround was to make a trait with a method that doesn't take `self` , and implement that trait rather than writing free-standing functions. Given any implementor, you can make a second implementor that decorates it – and you can convert the method to a function pointer by specifying the generic parameter.

That sounds interesting. I thought to somehow use traits too but I didn't want to burden the consumer of my library to implement a trait for every freestanding function they give.

It seems that they'll have to create a dummy type so that they could do `impl Trait for Dummy`. I wonder if there is a way around that boilerplate?

> [@CAD97](#):
>
> In the mean time, you might try picking out a crate that'll give you `StackBox<dyn Fn()>` . It'll necessarily be a bit bigger than `fn()` would be, but it'll accomplish what you want.

`Box<dyn Fn()>` alone will fit my needs, considering the fact that function item types are ZST so I don't think any actual allocation will happen. I'm mostly trying to avoid the additional size and indirection of `dyn Fn()`, which may be costly as this is likely going to be one of the hottest loop in my code.

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [June 14, 2021, 1:50am UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/7 "2021-06-14T01:50:56Z")

</div>

> [@DefinitelyNotRobot](#):
>
> It seems that they'll have to create a dummy type so that they could do `impl Trait for Dummy` . I wonder if there is a way around that boilerplate?

The most brute-force way around boilerplate is a macro. If you're willing to do a bunch of work as the library author, you could make a proc macro that the user can just apply as an attribute to their function, which would leave the function unmodified but also make a dummy type and implement the trait for the dummy type in terms of the function.

---

<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:** [September 12, 2021, 1:51am UTC](https://internals.rust-lang.org/t/suggestion-implement-default-for-function-items/14875/8 "2021-09-12T01:51:17Z")

</div>

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