Repository navigation
Fn trait doesn't allow impl returns (impl Fn() -> impl Trait), which is inconsistent with all other traits #101968
Description
Activity
- changed the title
[-]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[/+]on 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() -> Retsyntax is parsed or converted to a bound?
(link to playground)Note that writing
impl Fn<(), Output = impl Future<Output = bool>>with#![feature(unboxed_closures)]does not give the error...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:
#![feature(unboxed_closures)] use std::future::Future; fn less_than<'a>(number: &'a i32) -> impl FnOnce<(i32,), Output = impl Future<Output = bool> + 'a> { move |n: i32| async move { n < *number } } fn main() { let zero = 0; let less_than_zero = less_than(&zero); }Compilation output:
error: concrete type differs from previous defining opaque type use --> src/lib.rs:6:19 | 6 | move |n: i32| async move { n < *number } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `impl Future<Output = bool>`, got `impl Future<Output = bool>` | note: previous use here --> src/lib.rs:6:5 | 6 | move |n: i32| async move { n < *number } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> src/lib.rs:5:67 | 5 | fn less_than<'a>(number: &'a i32) -> impl FnOnce<(i32,), Output = impl Future<Output = bool> + 'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot resolve opaque type For more information about this error, try `rustc --explain E0720`.@jpalaciosdev: That regressed in #96727 cc @oli-obk
Seems to be a problem with RPIT inference in borrowck
Reacted by jpalaciosdev- moved this to Can do after stabilization in type alias impl trait stabilization
on Sep 21, 2022 A bit of an update:
future_closurefrom the original issue now works with#:#![feature(impl_trait_in_fn_trait_return)] use core::future::Future; fn future_closure() -> impl Fn() -> impl Future<Output = bool> { let f = || async { true }; f }
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:
fn future_closure_arg(arg: impl Fn() -> impl Future<Output = bool>) {} // => fn future_closure_arg<Fut: Future<Output = bool>>(arg: impl Fn() -> Fut) {}
Reacted by Paul Young, aWeinzierl and Zero-C-Star- Repository owner moved this from Can do after stabilization to Done in type alias impl trait stabilization
on Oct 31, 2022
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
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 Traitwhile allowingimpl Trait<T = impl Trait>which seems inconsistent.Here is my minimal reproduction code:
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:
Meta
rustc --version --verbose: