Repository: rust
Issue: Wrongly typing a collect with async streams causes confusing error messages alongside a cascade of unhelpful error messages
Labels: A-diagnostics,T-compiler,A-async-await,AsyncAwait-Triaged

Given the following code: <!-- Please provide a link to play.rust-lang.org -->

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=05ab45beb0f9d4f2f7cdd9fc89f17a03

```rust
use futures::stream::{self, StreamExt};

#[tokio::main]
async fn main() {
    let key1: String = "/helloa".to_string();

    dbg!(&key1);

    let futlist = stream::iter(0..10);
    let _stringvec: Vec<String> = futlist.map(move |_| {
        async {
            key1.clone();
        }
    }).buffer_unordered(10).collect::<Vec<String>>().await;
}
```

The current output is:

```
   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Vec<String>: Extend<()>` is not satisfied
  --> src/main.rs:14:29
   |
14 |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   |                             ^^^^^^^ the trait `Extend<()>` is not implemented for `Vec<String>`
   |
   = help: the following implementations were found:
             <Vec<T, A> as Extend<&'a T>>
             <Vec<T, A> as Extend<T>>

error[E0277]: the trait bound `Vec<String>: Extend<()>` is not satisfied
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^ the trait `Extend<()>` is not implemented for `Vec<String>`
   |
   = help: the following implementations were found:
             <Vec<T, A> as Extend<&'a T>>
             <Vec<T, A> as Extend<T>>
   = note: required because of the requirements on the impl of `futures::Future` for `Collect<BufferUnordered<futures::stream::Map<futures::stream::Iter<std::ops::Range<{integer}>>, [closure@src/main.rs:10:47: 14:6]>>, Vec<String>>`
   = note: required by `futures::Future::poll`

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:9:9
   |
9  |     let futlist = stream::iter(0..10);
   |         ^^^^^^^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:10:35
   |
10 |     let _stringvec: Vec<String> = futlist.map(move |_| {
   |                                   ^^^^^^^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:10:47
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  _______________________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |_____^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |______^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |___________________________^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |____________________________________________________^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^ cannot infer type for type `{integer}`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:10:35
   |
10 |       let _stringvec: Vec<String> = futlist.map(move |_| {
   |  ___________________________________^
11 | |         async {
12 | |             key1.clone();
13 | |         }
14 | |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   | |__________________________________________________________^

error: aborting due to 9 previous errors

Some errors have detailed explanations: E0277, E0698.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `playground`

To learn more, run the command again with --verbose.
```

Ideally the output should look like:

```
   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Vec<String>: Extend<()>` is not satisfied
  --> src/main.rs:14:29
   |
14 |     }).buffer_unordered(10).collect::<Vec<String>>().await;
   |                             ^^^^^^^ the trait `Extend<()>` is not implemented for `Vec<String>`
   |
   = help: the following implementations were found:
             <Vec<T, A> as Extend<&'a T>>
             <Vec<T, A> as Extend<T>>
```

I guess just the first error shows what the problem is, but it's still a bit scary for a newcomer. Perhaps a nice sentence like "Collect expected a stream of strings, but got a stream of unity types ()"

Even better would be a suggestion to remove the semicolon so that strings are returned, but I can understand that that analysis may be very complex, and it may be hard to avoid making suggestions that are not what the user intended.

The cascade is somewhat similar to #85131 but unlike with #85131, where the main error message is already decent, I think the main error could also be made a bit better here.