Skip to content

Fn trait doesn't allow impl returns (impl Fn() -> impl Trait), which is inconsistent with all other traits #101968

Closed
@arduano

Description

@arduano

I've been working on a functional interface for a library which relies on code generation, so I have functions returning functions, however I've hit a roadblock with functions returning closures which return traits (without resorting to dynamic dispatch).

The compiler doesn't allow impl Fn() -> impl Trait while allowing impl Trait<T = impl Trait> which seems inconsistent.

Here is my minimal reproduction code:

// This works of course
fn closure() -> impl Fn() -> bool {
    let f = || true;
    f
}

// Error
// `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
fn future_closure() -> impl Fn() -> impl Future<Output = bool> {
    let f = || async { true };
    f
}

// Same error
fn future_closure_arg(arg: impl Fn() -> impl Future<Output = bool>) {}

// This works though
fn iter_impl(arg: impl Iterator<Item = impl Future<Output = bool>>) {}

However, seems like wrapping the Fn in another trait fixes the error, so this doesn't appear to be a functionality limitation but more of an oversight:

// This compiles fine

trait Func {
    type T;
    fn call(&self) -> Self::T;
}

impl<F: Fn() -> R, R> Func for F {
    type T = R;

    fn call(&self) -> Self::T {
        self()
    }
}

fn future_trait_closure() -> impl Func<T = impl Future<Output = bool>> {
    let f = || async { true };
    f
}

Meta

rustc --version --verbose:

rustc 1.63.0 (4b91a6ea7 2022-08-08)
binary: rustc
commit-hash: 4b91a6ea7258a947e59c6522cd5898e7c0a6a88f
commit-date: 2022-08-08
host: x86_64-unknown-linux-gnu
release: 1.63.0
LLVM version: 14.0.5

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions