Closed
Description
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
Type
Projects
Status
Done
Milestone
Relationships
Development
No branches or pull requests
Activity
[-]Fn trait doesn't allow impl returns, which is inconsistent with all other traits[/-][+]Fn trait doesn't allow impl returns (impl Fn() -> impl Trait), which is inconsistent with all other traits[/+]zachs18 commentedon Sep 18, 2022
Note that writing
impl Fn<(), Output = impl Future<Output = bool>>
with#![feature(unboxed_closures)]
does not give the error, so perhaps its something to do with howFn() -> Ret
syntax is parsed or converted to a bound?(link to playground)
jpalaciosdev commentedon Sep 20, 2022
Just a quick note: compilation still fails for some code using the latest nightly builds (though it used to compile fine with older ones, such as nightly-2022-06-29). For example:
Compilation output:
Link to playground.
compiler-errors commentedon Sep 20, 2022
@jpalaciosdev: That regressed in #96727 cc @oli-obk
Seems to be a problem with RPIT inference in borrowck
async fn
in trait withimpl Trait
return fails to compile #102688impl Trait
in traits #101679impl Fn() -> impl Trait
in return position #93582WaffleLapkin commentedon Oct 31, 2022
A bit of an update:
future_closure
from the original issue now works with#![feature(impl_trait_in_fn_trait_return)]
(tracking issue):Can this be closed then?
As a side note in argument position it still doesn't work (because we may want to special case fn trait syntax to work better with lifetimes...), however it's easy to transform APIT into a generic: