Skip to content

Commit

Permalink
Rollup merge of #93582 - WaffleLapkin:rpitirpit, r=compiler-errors
Browse files Browse the repository at this point in the history
Allow `impl Fn() -> impl Trait` in return position

_This was originally proposed as part of #93082 which was [closed](rust-lang/rust#93082 (comment)) due to allowing `impl Fn() -> impl Trait` in argument position._

This allows writing the following function signatures:
```rust
fn f0() -> impl Fn() -> impl Trait;
fn f3() -> &'static dyn Fn() -> impl Trait;
```

These signatures were already allowed for common traits and associated types, there is no reason why `Fn*` traits should be special in this regard.

`impl Trait` in both `f0` and `f3` means "new existential type", just like with `-> impl Iterator<Item = impl Trait>` and such.

Arrow in `impl Fn() ->` is right-associative and binds from right to left, it's tested by [this test](https://github.com/WaffleLapkin/rust/blob/a819fecb8dea438fc70488ddec30a61e52942672/src/test/ui/impl-trait/impl_fn_associativity.rs).

There even is a test that `f0` compiles:
https://github.com/rust-lang/rust/blob/2f004d2d401682e553af3984ebd9a3976885e752/src/test/ui/impl-trait/nested_impl_trait.rs#L25-L28

But it was changed in [PR 48084 (lines)](https://github.com/rust-lang/rust/pull/48084/files#diff-ccecca938872d65ffe8cd1c3ef1956e309fac83bcda547d8b16b89257e53a437R37)  to test the opposite, probably unintentionally given [PR 48084 (lines)](https://github.com/rust-lang/rust/pull/48084/files#diff-5a02f1ed43debed1fd24f7aad72490064f795b9420f15d847bac822aa4621a1cR476-R477).

r? `@nikomatsakis`

----

This limitation is especially annoying with async code, since it forces one to write this:
```rust
trait AsyncFn3<A, B, C>: Fn(A, B, C) -> <Self as AsyncFn3<A, B, C>>::Future {
    type Future: Future<Output = Self::Out>;

    type Out;
}

impl<A, B, C, Fut, F> AsyncFn3<A, B, C> for F
where
    F: Fn(A, B, C) -> Fut,
    Fut: Future,
{
    type Future = Fut;

    type Out = Fut::Output;
}

fn async_closure() -> impl AsyncFn3<i32, i32, i32, Out = u32> {
    |a, b, c| async move { (a + b + c) as u32 }
}
```
Instead of:
```rust
fn async_closure() -> impl Fn(i32, i32, i32) -> impl Future<Output = u32> {
    |a, b, c| async move { (a + b + c) as u32 }
}
```
  • Loading branch information
Dylan-DPC authored Oct 30, 2022
2 parents b776a79 + a081fc7 commit e30f474
Showing 0 changed files with 0 additions and 0 deletions.

0 comments on commit e30f474

Please sign in to comment.