Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inference of argument type of async closure is broken #127468

Closed
kriomant opened this issue Jul 7, 2024 · 1 comment · Fixed by #127482
Closed

Inference of argument type of async closure is broken #127468

kriomant opened this issue Jul 7, 2024 · 1 comment · Fixed by #127482
Labels
C-bug Category: This is a bug.

Comments

@kriomant
Copy link

kriomant commented Jul 7, 2024

Well, it is maybe not a regression technically, because I use unstable feature. However, I wouldn't like this to get into stable channel.

Code

I tried this code:

#![feature(async_closure)]

use std::future::Future;

pub struct A {}
impl A {
    fn method(&self) {}
}

pub fn call<B, F>(f: F)
    where F: FnOnce(A) -> B, B: Future<Output=()>
{
    f(A {});
}

pub fn test() {
    call(async move |a| {
        a.method();
    });
}

I expected to see this happen: I don't have to specify type of 'a' parameter as it may be inferred from call signature.

Instead, this happened:

error[E0282]: type annotations needed
  --> src/lib.rs:18:9
   |
18 |         a.method();
   |         ^ cannot infer type

I did compiler bisection, here is the result:

searched nightlies: from nightly-2023-03-17 to nightly-2024-06-12
regressed nightly: nightly-2024-02-07
searched commit range: https://github.com/rust-lang/rust/compare/f067fd6084d750f3797f54b71771c5dbc149726f...256b6fb19a2c018eaad4806d2369d1f6a71fc6ec
regressed commit: https://github.com/rust-lang/rust/commit/4a2fe4491ea616983a0cf0cbbd145a39768f4e7a

<details>
<summary>bisected with <a href='https://github.com/rust-lang/cargo-bisect-rustc'>cargo-bisect-rustc</a> v0.6.8</summary>


Host triple: x86_64-unknown-linux-gnu
Reproduce with:
```bash
cargo bisect-rustc --start 2023-03-17 --end 2024-06-12
```
@kriomant kriomant added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Jul 7, 2024
@rustbot rustbot added I-prioritize Issue: Indicates that prioritization has been requested for this issue. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jul 7, 2024
@compiler-errors
Copy link
Member

This is a duplicate of #127425.

Please rewrite your call function signature to use async Fn trait bounds to recover the signature inference: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=bdff766a5208c09f202caeed0735ee86

#![feature(async_closure)]

pub struct A {}
impl A {
    fn method(&self) {}
}

pub fn call<B, F>(f: F)
where
    F: async FnOnce(),
{
    f(A {});
}

pub fn test() {
    call(async move |a| {
        a.method();
    });
}

Or if you're passing an async closure to a library you do, then I recommend either ascribing the types of your arguments, or probably just change your async closure back to using || async {}, since there's nothing that async closures really buy you in this situation just yet.

@saethlin saethlin removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. regression-untriaged Untriaged performance or correctness regression. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jul 8, 2024
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jul 8, 2024
…g-inference, r=oli-obk

Infer async closure signature from (old-style) two-part `Fn` + `Future` bounds

When an async closure is passed to a function that has a "two-part" `Fn` and `Future` trait bound, like:

```rust
use std::future::Future;

fn not_exactly_an_async_closure(_f: F)
where
    F: FnOnce(String) -> Fut,
    Fut: Future<Output = ()>,
{}
```

The we want to be able to extract the signature to guide inference in the async closure, like:

```rust
not_exactly_an_async_closure(async |string| {
    for x in string.split('\n') { ... }
    //~^ We need to know that the type of `string` is `String` to call methods on it.
})
```

Closure signature inference will see two bounds: `<?F as FnOnce<Args>>::Output = ?Fut`, `<?Fut as Future>::Output = String`. We need to extract the signature by looking through both projections.

### Why?

I expect the ecosystem's move onto `async Fn` trait bounds (which are not affected by this PR, and already do signature inference fine) to be slow. In the mean time, I don't see major overhead to supporting this "old–style" of trait bounds that were used to model async closures.

r? oli-obk
Fixes rust-lang#127468
Fixes rust-lang#127425
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jul 8, 2024
Rollup merge of rust-lang#127482 - compiler-errors:closure-two-par-sig-inference, r=oli-obk

Infer async closure signature from (old-style) two-part `Fn` + `Future` bounds

When an async closure is passed to a function that has a "two-part" `Fn` and `Future` trait bound, like:

```rust
use std::future::Future;

fn not_exactly_an_async_closure(_f: F)
where
    F: FnOnce(String) -> Fut,
    Fut: Future<Output = ()>,
{}
```

The we want to be able to extract the signature to guide inference in the async closure, like:

```rust
not_exactly_an_async_closure(async |string| {
    for x in string.split('\n') { ... }
    //~^ We need to know that the type of `string` is `String` to call methods on it.
})
```

Closure signature inference will see two bounds: `<?F as FnOnce<Args>>::Output = ?Fut`, `<?Fut as Future>::Output = String`. We need to extract the signature by looking through both projections.

### Why?

I expect the ecosystem's move onto `async Fn` trait bounds (which are not affected by this PR, and already do signature inference fine) to be slow. In the mean time, I don't see major overhead to supporting this "old–style" of trait bounds that were used to model async closures.

r? oli-obk
Fixes rust-lang#127468
Fixes rust-lang#127425
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants