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

Unhelpful error on mismatched types for anonymous futures #125737

Closed
chriskrycho opened this issue May 29, 2024 · 3 comments · Fixed by #126215
Closed

Unhelpful error on mismatched types for anonymous futures #125737

chriskrycho opened this issue May 29, 2024 · 3 comments · Fixed by #126215
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. D-papercut Diagnostics: An error or lint that needs small tweaks. E-help-wanted Call for participation: Help is requested to fix this issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-async Working group: Async & await

Comments

@chriskrycho
Copy link
Contributor

chriskrycho commented May 29, 2024

Code

fn main() {
    let a = async { 1 };
    let b = async { 2 };
    
    let bad = vec![a, b];
}

Current output

error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
2 |     let a = async { 1 };
  |             ----------- the expected `async` block
3 |     let b = async { 2 };
  |             ----------- the found `async` block
4 |     
5 |     let bad = vec![a, b];
  |                       ^ expected `async` block, found a different `async` block
  |
  = note: expected `async` block `{async block@src/main.rs:2:13: 2:24}`
             found `async` block `{async block@src/main.rs:3:13: 3:24}`

For more information about this error, try `rustc --explain E0308`.

Desired output

error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
2 |     let a = async { 1 };
  |             ----------- the expected `async` block
3 |     let b = async { 2 };
  |             ----------- the found `async` block
4 |     
5 |     let bad = vec![a, b];
  |                       ^ <something better here!>
  |
  = note: expected `async` block `{async block@src/main.rs:2:13: 2:24}`
             found `async` block `{async block@src/main.rs:3:13: 3:30}`

  = note: the futures produced by async blocks always have unique types, even if
          they have the same output type.

For more information about this error, try `rustc --explain E0308`.

Rationale and extra context

Especially for people new to async, this message is extremely opaque. There is not actually enough information to understand it unless you already know (a) that async blocks produce an anonymous future type and (b) that regardless of the Output type, those futures are always unique and incompatible types. The message sort of implies this (“found a different async block”), but it is not actionable in any way.

It is pretty easy to get here by reaching for (to pick just one easy example) futures::future::join_all. I ended up stumbling across it in the process of building up some sample code for the new async chapter in the book, and I had a 🤨 moment at first!

I have the time to help fix this, so if someone can point me in the right direction and help get it landed, I would be delighted to do the work.

Other cases

No response

Rust Version

rustc 1.77.1 (7cf61ebde 2024-03-27)
binary: rustc
commit-hash: 7cf61ebde7b22796c69757901dd346d0fe70bd97
commit-date: 2024-03-27
host: aarch64-apple-darwin
release: 1.77.1
LLVM version: 17.0.6

Anything else?

No response

@chriskrycho chriskrycho added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 29, 2024
@fmease fmease added A-async-await Area: Async & Await D-papercut Diagnostics: An error or lint that needs small tweaks. labels May 30, 2024
@chriskrycho chriskrycho changed the title Bad error on mismatched types for anonymous futures Unhelpful error on mismatched types for anonymous futures May 30, 2024
@eholk
Copy link
Contributor

eholk commented Jun 6, 2024

This seems like a good suggestion. I'd suggest tweaking the wording a bit, since I don't know that the implications of async blocks having unique types are immediately obvious. Maybe something like this?

  = note: the futures produced by async blocks each have unique types, so every async
          block has a different type even if they have the same output type.

@traviscross
Copy link
Contributor

traviscross commented Jun 6, 2024

@rustbot labels +AsyncAwait-Triaged

We discussed this in our async call and agreed that some improvement along these lines would be good. We could wordsmith it in the PR of course.

(It'd be interesting too to add such diagnostics for closures and other similar cases.)

@rustbot rustbot added the AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. label Jun 6, 2024
@tmandry tmandry added the E-help-wanted Call for participation: Help is requested to fix this issue. label Jun 6, 2024
@traviscross traviscross added the WG-async Working group: Async & await label Jun 6, 2024
@yoshuawuyts
Copy link
Member

For reference, here's the error message for mismatched impl Traits (playground). Perhaps borrowing from this phrasing could be helpful here?

   = note: expected opaque type `impl BorkBork` (`Cat`)
              found opaque type `impl BorkBork` (`Dog`)
   = note: distinct uses of `impl Trait` result in different opaque types

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jun 10, 2024
…lcnr

Add explanatory note to async block type mismatch error

The async block type mismatch error might leave the user wondering as to why it occurred. The new note should give them the needed context.

Changes this diagnostic:
```
error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
2 |     let a = async { 1 };
  |             ----------- the expected `async` block
3 |     let b = async { 2 };
  |             ----------- the found `async` block
4 |
5 |     let bad = vec![a, b];
  |                       ^ expected `async` block, found a different `async` block
  |
  = note: expected `async` block `{async block@src/main.rs:2:13: 2:24}`
             found `async` block `{async block@src/main.rs:3:13: 3:24}`
```

to this:
```
error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
2 |     let a = async { 1 };
  |             ----------- the expected `async` block
3 |     let b = async { 2 };
  |             ----------- the found `async` block
4 |
5 |     let bad = vec![a, b];
  |                       ^ expected `async` block, found a different `async` block
  |
  = note: expected `async` block `{async block@src/main.rs:2:13: 2:24}`
             found `async` block `{async block@src/main.rs:3:13: 3:24}`
  = note: no two async blocks, even if identical, have the same type
  = help: consider pinning your async block and and casting it to a trait object
```

Fixes rust-lang#125737
@bors bors closed this as completed in f0adebc Jun 10, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jun 10, 2024
Rollup merge of rust-lang#126215 - gurry:125737-bad-err-anon-futs, r=lcnr

Add explanatory note to async block type mismatch error

The async block type mismatch error might leave the user wondering as to why it occurred. The new note should give them the needed context.

Changes this diagnostic:
```
error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
2 |     let a = async { 1 };
  |             ----------- the expected `async` block
3 |     let b = async { 2 };
  |             ----------- the found `async` block
4 |
5 |     let bad = vec![a, b];
  |                       ^ expected `async` block, found a different `async` block
  |
  = note: expected `async` block `{async block@src/main.rs:2:13: 2:24}`
             found `async` block `{async block@src/main.rs:3:13: 3:24}`
```

to this:
```
error[E0308]: mismatched types
 --> src/main.rs:5:23
  |
2 |     let a = async { 1 };
  |             ----------- the expected `async` block
3 |     let b = async { 2 };
  |             ----------- the found `async` block
4 |
5 |     let bad = vec![a, b];
  |                       ^ expected `async` block, found a different `async` block
  |
  = note: expected `async` block `{async block@src/main.rs:2:13: 2:24}`
             found `async` block `{async block@src/main.rs:3:13: 3:24}`
  = note: no two async blocks, even if identical, have the same type
  = help: consider pinning your async block and and casting it to a trait object
```

Fixes rust-lang#125737
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. D-papercut Diagnostics: An error or lint that needs small tweaks. E-help-wanted Call for participation: Help is requested to fix this issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-async Working group: Async & await
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants