Skip to content

Commit

Permalink
Rollup merge of #73672 - nellshamrell:async-fix, r=estebank
Browse files Browse the repository at this point in the history
Adds a clearer message for when the async keyword is missing from a f…

…unction

This is a somewhat simple fix for #66731.

Under the current version of Rust, if a user has a rust file that looks like this:

```rust
fn boo (){}

async fn foo() {
    boo().await;
}

fn main() {

}
```

And they attempt to run it, they will receive an error message that looks like this:

```bash
error: incorrect use of `await`                                                                                                        --> test.rs:4:14                                                                                                                       |                                                                                                                                   4 |     boo.await();                                                                                                                    |              ^^ help: `await` is not a method call, remove the parentheses                                                                                                                                                                                              error[E0277]: the trait bound `fn() {boo}: std::future::Future` is not satisfied                                                        --> test.rs:4:5                                                                                                                        |                                                                                                                                  4  |     boo.await();                                                                                                                    |     ^^^^^^^^^ the trait `std::future::Future` is not implemented for `fn() {boo}`                                                                                                                                                                                      error: aborting due to 2 previous errors                                                                                                                                                                                                                                    For more information about this error, try `rustc --explain E0277`.
```

This is not very clear.

With the changes made in this PR, when a user compiles and runs that same rust code, they will receive an error message that looks like this:

```bash
error[E0277]: `()` is not a future.
 --> test.rs:4:5
  |
4 |     boo().await;
  |     ^^^^^^^^^^^ `()` is not a future
  |
  = help: the trait `std::future::Future` is not implemented for `()`
  = note: required by `std::future::Future::poll`
```

In the future, I think we should make this error message even clearer, perhaps through a solution like the one described in [this comment](#66731 (comment)). However, as that potentially involves a major change proposal, I would rather get this change in now and make the error message a little clearer while an MCP is drafted and discussed.

Signed-off-by: Nell Shamrell <nellshamrell@gmail.com>
  • Loading branch information
Manishearth committed Jun 28, 2020
2 parents 45ec25e + 5e28eb5 commit d227a82
Show file tree
Hide file tree
Showing 9 changed files with 22 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/libcore/future/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::task::{Context, Poll};
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[lang = "future_trait"]
#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")]
pub trait Future {
/// The type of value produced on completion.
#[stable(feature = "futures_api", since = "1.36.0")]
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/async-error-span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use std::future::Future;

fn get_future() -> impl Future<Output = ()> {
//~^ ERROR the trait bound `(): std::future::Future` is not satisfied
//~^ ERROR `()` is not a future
panic!()
}

Expand Down
5 changes: 3 additions & 2 deletions src/test/ui/async-await/async-error-span.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
error[E0277]: the trait bound `(): std::future::Future` is not satisfied
error[E0277]: `()` is not a future
--> $DIR/async-error-span.rs:7:20
|
LL | fn get_future() -> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `()`
| ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
LL |
LL | panic!()
| -------- this returned value is of type `!`
|
= help: the trait `std::future::Future` is not implemented for `()`
= note: the return type of a function must have a statically known size

error[E0698]: type inside `async fn` body must be known in this context
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/async-await/issue-70594.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ async fn fun() {
//~| error: `.await` is not allowed in a `const`
//~| error: `loop` is not allowed in a `const`
//~| error: `.await` is not allowed in a `const`
//~| error: the trait bound `(): std::future::Future` is not satisfied
//~| error: `()` is not a future
}

fn main() {}
5 changes: 3 additions & 2 deletions src/test/ui/async-await/issue-70594.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ error[E0744]: `.await` is not allowed in a `const`
LL | [1; ().await];
| ^^^^^^^^

error[E0277]: the trait bound `(): std::future::Future` is not satisfied
error[E0277]: `()` is not a future
--> $DIR/issue-70594.rs:4:9
|
LL | [1; ().await];
| ^^^^^^^^ the trait `std::future::Future` is not implemented for `()`
| ^^^^^^^^ `()` is not a future
|
= help: the trait `std::future::Future` is not implemented for `()`
= note: required by `std::future::Future::poll`

error: aborting due to 5 previous errors
Expand Down
5 changes: 3 additions & 2 deletions src/test/ui/async-await/issues/issue-62009-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ LL | fn main() {
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks

error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]: std::future::Future` is not satisfied
error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future
--> $DIR/issue-62009-1.rs:12:5
|
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`
| ^^^^^^^^^^^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` is not a future
|
= help: the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]`
= note: required by `std::future::Future::poll`

error: aborting due to 4 previous errors
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues-71798.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
*x //~^ ERROR the trait bound `u32: std::future::Future` is not satisfied
*x //~^ ERROR `u32` is not a future
}

fn main() {
Expand Down
5 changes: 3 additions & 2 deletions src/test/ui/issues-71798.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ error[E0425]: cannot find value `u` in this scope
LL | let _ = test_ref & u;
| ^ not found in this scope

error[E0277]: the trait bound `u32: std::future::Future` is not satisfied
error[E0277]: `u32` is not a future
--> $DIR/issues-71798.rs:1:25
|
LL | fn test_ref(x: &u32) -> impl std::future::Future<Output = u32> + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `u32`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future
LL | *x
| -- this returned value is of type `u32`
|
= help: the trait `std::future::Future` is not implemented for `u32`
= note: the return type of a function must have a statically known size

error: aborting due to 2 previous errors
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `fn() -> impl std::future::Future {foo}: std::future::Future` is not satisfied
error[E0277]: `fn() -> impl std::future::Future {foo}` is not a future
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9
|
LL | async fn foo() {}
Expand All @@ -8,14 +8,15 @@ LL | fn bar(f: impl Future<Output=()>) {}
| ----------------- required by this bound in `bar`
...
LL | bar(foo);
| ^^^ the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
| ^^^ `fn() -> impl std::future::Future {foo}` is not a future
|
= help: the trait `std::future::Future` is not implemented for `fn() -> impl std::future::Future {foo}`
help: use parentheses to call the function
|
LL | bar(foo());
| ^^

error[E0277]: the trait bound `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]: std::future::Future` is not satisfied
error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
|
LL | fn bar(f: impl Future<Output=()>) {}
Expand All @@ -24,8 +25,9 @@ LL | fn bar(f: impl Future<Output=()>) {}
LL | let async_closure = async || ();
| -------- consider calling this closure
LL | bar(async_closure);
| ^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
| ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
|
= help: the trait `std::future::Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
help: use parentheses to call the closure
|
LL | bar(async_closure());
Expand Down

0 comments on commit d227a82

Please sign in to comment.