2

It is easy to wrap the inner closure inside a Box:

fn add1() -> impl Fn(i32) -> Box<Fn(i32) -> i32> {
    |x| Box::new(|y| x + y)
}

But is it necessary to use a Box? In the following code:

fn add2() -> ?? {
    |x: i32| move |y: i32| x + y
}

Can I replace ?? with something to make the code type check?

EFanZh
  • 2,357
  • 3
  • 30
  • 63

1 Answers1

4

No. As you are already aware, impl Trait is the mechanism to return an instance of a trait without boxing.

If you try to extend this:

fn add2() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
    |x| |y| x + y
}

The compiler tells you:

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
 --> src/lib.rs:9:30
  |
9 | fn add2() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
  |                              ^^^^^^^^^^^^^^^^^^^

From the impl Trait RFC, emphasis mine:

impl Trait may only be written within the return type of a freestanding or inherent-impl function, not in trait definitions or any non-return type position. They may also not appear in the return type of closure traits or function pointers, unless these are themselves part of a legal return type.

  • Eventually, we will want to allow the feature to be used within traits

The return type of a closure is an associated type of the closure trait:

pub trait FnOnce<Args> {
    type Output;
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366