Repository: rust
Issue: Confusing `is required to live as long as 'static` compiler error message involving trait return
Labels: A-diagnostics,A-lifetimes,A-borrow-checker,T-compiler,D-terse

The following reproduce case (which could almost certainly be reduced further) demonstrates what I think is a confusing, not-very-actionable error message which fails to live up to Rust's typically high bar for error message quality.

First, the error message:

```
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  --> src/lib.rs:55:35
   |
55 |     pub async fn async_entrypoint(&self, writer: &Writer, threads: usize) -> Result<(), String> {
   |                                   ^^^^^
   |                                   |
   |                                   this data with an anonymous lifetime `'_`...
   |                                   ...is captured here...
...
58 |                 .map(|reader| writer.write_path(reader.reader)),
   |                                                 ------------- ...and is required to live as long as `'static` here

For more information about this error, try `rustc --explain E0759`.
error: could not compile `static-bad-error` due to previous error
```

The reason I find this error confusing is:

a) `'static` appears nowhere in this code.
b) It doesn't tell me where that `'static` lifetime requirement is coming from.

In other error messages related to lifetimes, the compiler prints out additional context to tell me where lifetime constraints are coming from. Here, we get nothing and I'm left scratching my head.

That is, unless I run `rustc --explain E0759`, which tells me this has something to do with return types involving a trait and `'static` lifetimes. So that actually leads me somewhere useful.

However, the rub is that Rust's default compiler error messages are usually so good that I've been conditioned to ignore those `rustc --explain` suggestions because the error message itself usually surfaces sufficient context. I (embarrassingly) probably wasted >1 hour trying code variations to make this error go away before running `rustc --explain E0759`!

Potentially adding to the confusion was the error was introduced when I added `async fn async_entrypoint()`. So I thought the error must have something to do with `async` or that specific function. The code compiled fine before I added this function, so I thought all lifetime annotations and such on the functions it depends on were fine. However, something about `async` or this function appears to have tickled this E0759 issue. I'm honestly still unsure what.

Potential solutions that would make this error message better:

a) Tell me where the implicit `'static` requirement is coming from. In this case, I have multiple functions in the call chain that could be the source of the error. Which one is the problem?
b) Potentially suggest a workaround to avoid `'static` requirements. Should I wrap in `Box<T>`? Should I add a `+ '_` or `+ 'a` bound?

```rust
// Requires 'futures = "0.3"' in Cargo.toml.
use {
    futures::{AsyncRead, StreamExt, TryStreamExt},
    std::pin::Pin,
};

pub struct Writer {}

impl Writer {
    async fn write_path(
        &self,
        reader: Pin<Box<dyn AsyncRead + Send>>,
    ) -> Result<u64, &'static str> {
        todo!()
    }
}

pub struct Reader<'a> {
    pub reader: Pin<Box<dyn AsyncRead + Send + 'a>>,
}

#[derive(Debug, Default)]
pub struct MyStruct {
    els: Vec<String>,
}

impl MyStruct {
    pub fn box_iter(&self) -> Box<dyn Iterator<Item = &'_ str> + Send + '_> {
        Box::new(self.els.iter().map(|x| x.as_str()))
    }

    pub fn reader_from_els_iter(&self) -> impl AsyncRead + '_ {
        futures::stream::iter(self.box_iter().map(|p| Ok(p.to_string()))).into_async_read()
    }

    pub fn iter_of_readers(&self) -> impl Iterator<Item = Reader<'_>> + '_ {
        std::iter::once(Reader {
            reader: Box::pin(self.reader_from_els_iter()),
        })
    }

    pub async fn async_entrypoint(&self, writer: &Writer, threads: usize) -> Result<(), String> {
        let mut fs = futures::stream::iter(
            self.iter_of_readers()
                .map(|reader| writer.write_path(reader.reader)),
        )
        .buffer_unordered(threads);

        while let Some(res) = fs.next().await {
            res?;
        }

        Ok(())
    }
}
```

<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":null}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->