Skip to content

Incomprehensible error message involving lifetimes adding extension methods to dyn Trait #71341

New issue

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

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

Already on GitHub? # to your account

Closed
rocallahan opened this issue Apr 20, 2020 · 5 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@rocallahan
Copy link

I'm defining a trait that adds extension methods to dyn <another-trait>:

impl GeneralControlCursorRendering for dyn GeneralControlCursor {
    fn render_frame_container_view<'a>(
        &'a self,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
        Box::pin(async move {})
    }
}

Complete example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9918f3c4541601415f65606b4bfa0790

Rust stable and nightly both give

error: cannot infer an appropriate lifetime
  --> src/main.rs:25:16
   |
25 |         cursor.render_frame_container_view().await;
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                |
   |                this return type evaluates to the `'static` lifetime...
   |                ...but this borrow...
   |
note: ...can't outlive the lifetime `'a` as defined on the function body at 21:17
  --> src/main.rs:21:17
   |
21 | fn report_frame<'a>(
   |                 ^^
help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 21:17
   |
23 | ) -> impl Future<Output = ()> + Send + 'a + 'a {
   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is confusing. Obviously, adding a lifetime parameter identical to one already present doesn't seem sensible. Furthermore there is no clue here indicating what the error actually is. I spent over an hour thrashing around and ended up with https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fda63d48e1652dcfd0923002f723163c --- i.e. I need to add a lifetime bound to the dyn type I'm extending, not just the method(s) on the extension.

I'm assuming that the compiler is correct here and it just needs a better error message. I'm not 100% sure about that though.

@rocallahan rocallahan added the C-bug Category: This is a bug. label Apr 20, 2020
@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 20, 2020
@estebank
Copy link
Contributor

Current output:

error[E0759]: cannot infer an appropriate lifetime
  --> src/main.rs:25:16
   |
22 |     cursor: &'a dyn GeneralControlCursor,
   |             ---------------------------- this data with lifetime `'a`...
...
25 |         cursor.render_frame_container_view().await;
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here

@Aaron1011
Copy link
Member

Aaron1011 commented Jun 26, 2020

Minimized:

trait OtherTrait<'a> {}
impl<'a> OtherTrait<'a> for &'a () {}

trait ObjectTrait {}
trait MyTrait {
    fn use_self(&self) -> &();
}

impl MyTrait for dyn ObjectTrait {
    fn use_self(&self) -> &() { panic!() }
}

fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
    val.use_self()
}
error[E0759]: cannot infer an appropriate lifetime
  --> src/lib.rs:14:9
   |
13 | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
   |                    ------------------- this data with lifetime `'a`...
14 |     val.use_self()
   |         ^^^^^^^^ ...is captured and required to live as long as `'static` here

The very non-obvious fix is to change impl MyTrait for dyn ObjectTrait to impl MyTrait for dyn ObjectTrait + '_. In the original example, this corresponds to changing impl GeneralControlCursorRendering for dyn GeneralControlCursor to impl GeneralControlCursorRendering for dyn GeneralControlCursor + '_.

The issue here is that impl MyTrait for dyn ObjectTrait gets desugared to impl MyTrait for dyn ObjectTrait + 'static - however, the error message does not explain this.

@estebank estebank added D-confusing Diagnostics: Confusing error or lint that should be reworked. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. and removed D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. labels Jun 26, 2020
@estebank
Copy link
Contributor

@Aaron1011 with #73783 applied:

Screen Shot 2020-06-26 at 6 52 37 PM

I would love it if we could have a more reliable way of addressing this, but at least it is a start.

estebank added a commit to estebank/rust that referenced this issue Jun 28, 2020
Manishearth added a commit to Manishearth/rust that referenced this issue Jul 17, 2020
…time, r=nikomatsakis

Detect when `'static` obligation might come from an `impl`

Partly address rust-lang#71341.
estebank added a commit to estebank/rust that referenced this issue Jul 20, 2020
Manishearth added a commit to Manishearth/rust that referenced this issue Jul 22, 2020
…time, r=nikomatsakis

Detect when `'static` obligation might come from an `impl`

Partly address rust-lang#71341.
estebank added a commit to estebank/rust that referenced this issue Jul 22, 2020
Manishearth added a commit to Manishearth/rust that referenced this issue Jul 22, 2020
…time, r=nikomatsakis

Detect when `'static` obligation might come from an `impl`

Partly address rust-lang#71341.
@estebank
Copy link
Contributor

estebank commented Sep 2, 2020

Current output:

error[E0759]: `cursor` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
  --> src/main.rs:25:16
   |
22 |     cursor: &'a dyn GeneralControlCursor,
   |             ---------------------------- this data with lifetime `'a`...
...
25 |         cursor.render_frame_container_view().await;
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
   |
note: the used `impl` has a `'static` requirement
  --> src/main.rs:13:44
   |
13 | impl GeneralControlCursorRendering for dyn GeneralControlCursor {
   |                                            ^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
14 |     fn render_frame_container_view<'a>(
   |        --------------------------- calling this method introduces the `impl`'s 'static` requirement
help: consider relaxing the implicit `'static` requirement
   |
13 | impl GeneralControlCursorRendering for dyn GeneralControlCursor + '_ {
   |                                                                 ^^^^
error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
  --> src/lib.rs:14:9
   |
13 | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
   |                    ------------------- this data with lifetime `'a`...
14 |     val.use_self()
   |         ^^^^^^^^ ...is captured and required to live as long as `'static` here
   |
note: the used `impl` has a `'static` requirement
  --> src/lib.rs:9:22
   |
9  | impl MyTrait for dyn ObjectTrait {
   |                      ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
10 |     fn use_self(&self) -> &() { panic!() }
   |        -------- calling this method introduces the `impl`'s 'static` requirement
help: consider relaxing the implicit `'static` requirement
   |
9  | impl MyTrait for dyn ObjectTrait + '_ {
   |                                  ^^^^

I think this ticket can be closed now, but for some reason I didn't with the PR (and I don't recall why).

@rocallahan
Copy link
Author

I agree, thanks for fixing this!!!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. 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

4 participants