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

Superfluous errors for missing lifetime in async function argument #76938

Open
djc opened this issue Sep 19, 2020 · 1 comment
Open

Superfluous errors for missing lifetime in async function argument #76938

djc opened this issue Sep 19, 2020 · 1 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. C-enhancement Category: An issue proposing an enhancement or a PR with one. D-verbose Too much output caused by a single piece of incorrect code T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@djc
Copy link
Contributor

djc commented Sep 19, 2020

In the example below (which is a little convoluted -- sorry, I already spent quite a bit reducing it), I'm getting what amounts to three compiler errors. But, when I fix the cause of the first error by applying the suggested fix, the other two errors go away. It feels like the compiler could be smarter about this and only throw the first diagnostic.

I tried this code:

use futures::stream::FuturesUnordered;
use http::Response;
use hyper::body::Body;

pub(crate) mod name {
    use super::*;
    pub(crate) async fn handler(cx: Context) -> Result<Response<Body>, ()> {
        let app = &cx.app;
        let name = cx.s();
        let query = cx.query();
        call(app, name, query).await
    }
    pub(crate) async fn call(app: &App, name: &str, query: Query) -> Result<Response<Body>, ()> {
        let stream = FuturesUnordered::new();
        stream.push(async move { Ok::<_, serde_json::Error>(format!("{}", true).into_bytes()) });
        Ok(Response::builder().body(Body::wrap_stream(stream)).unwrap())
    }
}

struct Context {
    app: App,
    s: String,
}

struct App {}

impl Context {
    fn s(&self) -> &str {
        &self.s
    }
    fn query(&self) -> Query {
        Query { s: &self.s }
    }
}

struct Query<'a> {
    s: &'a str,
}

(Playground.)

This is the compiler output I got:

error[E0726]: implicit elided lifetime not allowed here
  --> src/lib.rs:16:16
   |
16 |         query: Query,
   |                ^^^^^- help: indicate the anonymous lifetime: `<'_>`

error[E0597]: `cx` does not live long enough
  --> src/lib.rs:10:21
   |
10 |         let query = cx.query();
   |                     ^^--------
   |                     |
   |                     borrowed value does not live long enough
   |                     argument requires that `cx` is borrowed for `'static`
11 |         call(app, name, query).await
12 |     }
   |     - `cx` dropped here while still borrowed

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
  --> src/lib.rs:17:10
   |
17 |     ) -> Result<Response<Body>, ()> {
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: hidden type `impl futures::Future` captures lifetime smaller than the function body
  --> src/lib.rs:17:10
   |
17 |     ) -> Result<Response<Body>, ()> {
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^

I expected to see this happen: it would be nice if I only got the first error (E0726). It seems like the compiler is substituting some placeholder lifetime in place of the missing lifetime which is making things worse, causing the two other errors. It seems reasonable to replace missing lifetimes with '_ instead (especially if that's the suggested fix anyway) instead, which would make the other errors go away and makes it easier to focus on the actual problem. For this particular case, I also find the second and third error highly opaque and not very actionable.

Meta

The same thing happens on both current stable (1.46.0) and latest nightly (rustc 1.48.0-nightly bbc6774 2020-09-18).

@djc djc added the C-bug Category: This is a bug. label Sep 19, 2020
@jonas-schievink jonas-schievink added A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. and removed C-bug Category: This is a bug. labels Sep 19, 2020
@JohnTitor JohnTitor added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Sep 19, 2020
@estebank estebank added the D-verbose Too much output caused by a single piece of incorrect code label Sep 20, 2020
@tmandry
Copy link
Contributor

tmandry commented Sep 22, 2020

We could behave as if the elided lifetime were explicit in lowering. Is there anything preventing that?

I also don't think this is problem is very specific to async-await.

@tmandry tmandry added the AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. label Sep 22, 2020
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. C-enhancement Category: An issue proposing an enhancement or a PR with one. D-verbose Too much output caused by a single piece of incorrect code T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants