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

Confusing error: Immutable reference to future is not a future #87211

Open
Darksonn opened this issue Jul 17, 2021 · 10 comments
Open

Confusing error: Immutable reference to future is not a future #87211

Darksonn opened this issue Jul 17, 2021 · 10 comments
Assignees
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-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Darksonn
Copy link
Contributor

Darksonn commented Jul 17, 2021

Given the following code:

async fn my_async_fn() {}

async fn foo() {
    tokio::select! {
        _ = &my_async_fn() => {},
    }
}

playground

The current output is:

error[E0599]: no method named `poll` found for struct `Pin<&mut &impl Future>` in the current scope
 --> src/lib.rs:5:5
  |
5 | /     tokio::select! {
6 | |         _ = &my_async_fn() => {}
7 | |     }
  | |_____^ method not found in `Pin<&mut &impl Future>`
  |
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

Given the following code:

async fn my_async_fn() {}

async fn foo() {
    let fut = &my_async_fn();
    tokio::pin!(fut);
    
    fut.await;
}

playground

The current output is:

error[E0277]: `&impl Future` is not a future
 --> src/lib.rs:8:5
  |
8 |     fut.await;
  |     ^^^^^^^^^ `&impl Future` is not a future
  |
  = help: the trait `Future` is not implemented for `&impl Future`
  = note: required because of the requirements on the impl of `Future` for `Pin<&mut &impl Future>`
  = note: required by `poll`

Given the following code:

async fn my_async_fn() {}

async fn foo() {
    let fut = &my_async_fn();
    
    fut.await;
}

playground

The current output is:

error[E0277]: `&impl Future` is not a future
 --> src/lib.rs:7:5
  |
7 |     fut.await;
  |     ^^^^^^^^^ `&impl Future` is not a future
  |
  = help: the trait `Future` is not implemented for `&impl Future`
  = note: required by `poll`

In all three cases, it would be very helpful if the compiler could explicitly call out that an immutable reference to a future is not a future. I see this relatively often in the Tokio discord where people put some extra ampersands in random places and get really confused when the error says "impl future is not future". The ampersand in the error is not enough to clue them in to what the issue is. Especially for the first case.

@Darksonn Darksonn 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 Jul 17, 2021
@estebank estebank added A-async-await Area: Async & Await D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. labels Jul 22, 2021
@rustbot rustbot added the AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. label Jul 23, 2021
@tmandry tmandry removed the AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. label Jul 23, 2021
@tmandry
Copy link
Member

tmandry commented Jul 23, 2021

Agreed that these could all be clearer. Immutable references to impl Future do not implement Future because you need to be able to mutate the future to poll it.

This is a great issue for someone relatively new to the compiler to pick up. Start by finding the source of each error message, then adding custom logic to print a specialized message for this particular case. (The individual error messages could be fixed one at a time.)

@tmandry
Copy link
Member

tmandry commented Jul 23, 2021

@rustbot label +AsyncAwait-Triaged +E-mentor +E-help-wanted

@rustbot rustbot added AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. labels Jul 23, 2021
@chazkiker2
Copy link
Contributor

@rustbot claim

@chazkiker2 chazkiker2 removed their assignment Aug 5, 2021
@chazkiker2
Copy link
Contributor

@rustbot claim

(did not mean to unassign myself... sorry that I have not been quick on this issue.)

@chazkiker2
Copy link
Contributor

hey @tmandry, I’ve been caught up with some life stuff and just have not had the whitespace to sit down and toy with this.

Sorry for delaying this issue, but I think I’m going to unassign myself for the time being. is that okay?

@chazkiker2 chazkiker2 removed their assignment Aug 17, 2021
@chazkiker2
Copy link
Contributor

@tmandry maybe this should return to “On Deck”?

@rahul-ar
Copy link

@rustbot claim

@rahul-ar
Copy link

The solution to this seems to be filtering the rust_on_unimplemented attribute of the Future trait with type &impl Future (for the last two errors) and using a customized label.

#[rustc_on_unimplemented(
    on(
        _Self = "&impl Future", 
        label = "immutable reference to a future does not implement a future",
    ), 
    label = "`{Self}` is not a future", message = "`{Self}` is not a future"
)]

But this is not giving the expected result even though the type of Self seems to be &impl Future as see in the error label. The full error is the same as the original even after this change:

error[E0277]: `&impl Future` is not a future
   --> main.rs:6:5
    |
6   |     fut.await;
    |     ^^^^^^^^^ `&impl Future` is not a future (mod)
    |
    = help: the trait `Future` is not implemented for `&impl Future`
note: required by `poll`

@tmandry thoughts?

@tmandry
Copy link
Member

tmandry commented Aug 25, 2021

@rahul-ar That's not terribly surprising, I wouldn't expect rustc_on_unimplemented to handle impl Trait very well.

You could find out why it's not handled (with debug logging). Or you can handle this case directly (for all &T where T: Future) in the diagnostic code that emits this error. That would be more general and I don't see how you'd express it in rustc_on_unimplemented.

We already print decent error messages for the general case (traits other than Future). Maybe we just need to make that path take precedence over rustc_on_unimplemented (but if a bunch of tests break, that's an indication that we'll want to restrict it to only futures.)

@estebank
Copy link
Contributor

I am surprised. You can look at where rustc_on_unimplemented is handled. It is a method that collects a Vec called flags, you can add an info!(?flags) at the end of that function to see what the types we are looking for are on _Self. It might be that what you need to use is _Self=&impl std::future::Future instead.

@tmandry tmandry moved this to Claimed in wg-async work Dec 8, 2022
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-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-papercut Diagnostics: An error or lint that needs small tweaks. E-help-wanted Call for participation: Help is requested to fix this issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
Status: Claimed
Development

No branches or pull requests

6 participants