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

async/await errors should not discuss "yield statements" #51751

Closed
sophiajt opened this issue Jun 24, 2018 · 10 comments · Fixed by #60586
Closed

async/await errors should not discuss "yield statements" #51751

sophiajt opened this issue Jun 24, 2018 · 10 comments · Fixed by #60586
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints AsyncAwait-Polish Async-await issues that are part of the "polish" area P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@sophiajt
Copy link
Contributor

Awesome to see async/await starting to light up. I poked around and hit a snag putting together a naive little example. Clearly, this example is probably missing a bit more to get it running, but I just wanted to point the error here doesn't quite help:

#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)]

async fn inc(limit: i64) -> i64 {
    limit + 1
}

fn main() {
    let result = inc(10000);
    let finished = await!(result);
}

For the above, you get:

error[E0627]: yield statement outside of generator literal
  --> src/main.rs:22:20
   |
22 |     let finished = await!(result);
   |                    ^^^^^^^^^^^^^^
   |
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

Which immediately makes you wonder "what yield statement?" I suspect one of the first things people will want to try is awaiting an async function, so we might want to gently point them in the right direction.

cc @estebank @cramertj

@cramertj
Copy link
Member

cramertj commented Jun 24, 2018

@jonathandturner Ugh-- thanks for pointing this out! This is an annoying result of the fact that await is currently implemented as a plain-old macro rather than something that hooks into the compiler. Error messages should be much better when await is built-in.

cc @eddyb

@kennytm kennytm added the A-diagnostics Area: Messages for errors, warnings, and lints label Jun 24, 2018
@eddyb
Copy link
Member

eddyb commented Jun 24, 2018

Closely related to #51719.

@brandonros
Copy link

@jonathandturner What ended up being the working code?

@eddyb
Copy link
Member

eddyb commented Jul 17, 2018

@brandonros You need to keep await! only in async fns. To actually execute async fns you want the futures crate (possibly futures-preview, not sure), or, more likely, tokio's event loop.
cc @alexcrichton

@brandonros
Copy link

brandonros commented Jul 20, 2018

@eddyb I apologize for the extreme lack of knowledge on the topic as I am still a beginner, but I am curious and excited to give Rust a shot once I understand how to use async/await. I am struggling to find any kind of clear example on the Internet (probably because all of this is still so fresh)

Are you saying it is not possible to call await! in main? Is it possible to make main async?

Regarding the futures create, I was under the impression all of the necessary moving pieces for futures/async/await were being brought in to the Rust compiler + standard library so that no external crates would be required.

Can somebody post a full example of what a simple "Hello world" level async/await/futures function would look like (including its invocation from main?)

This is the closest I can come up with what seems it might be in the right direction is

#![feature(async_await, await_macro, futures_api)]

use std::task::Executor;

async fn inc(limit: i64) -> i64 {
    limit + 1
}

async fn run() {
  let result = await!(inc(10000));

  println!("{}", result);
}

fn main() {
  Executor::spawn_obj(&self, run);
}

but this does not compile for many obvious reasons. I feel there isn't any documentation out there that shows how to piece together the new async/await language features with the new std::future library. I think a working example of the pasted above code would be pretty big for the "beginner" community trying to get on board with Rust and not be fragmented between the many different ways to do async code that currently exist (and are most likely outdated/going to get phased out it sounds like with these new RFCs)

@eddyb
Copy link
Member

eddyb commented Jul 20, 2018

@brandonros I expect any practical usecase would still involve a tokio dependency (which would implement the executor & waker, for integrating async I/O and other async functionality).
This is a bit offtopic though, I'm guessing you also asked on reddit? That's a better discussion place.

@estebank estebank added the A-async-await Area: Async & Await label Jan 30, 2019
@nikomatsakis nikomatsakis changed the title async/await error message could be better async/await errors should not discuss "yield statements" Feb 22, 2019
@gilescope
Copy link
Contributor

Would some wording like this work:
"yield statement outside of generator literal (Maybe async called from a non-async context?)"

@nikomatsakis nikomatsakis added AsyncAwait-Polish Async-await issues that are part of the "polish" area P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 5, 2019
@gilescope
Copy link
Contributor

I can see we have asyncness on the ast. Given that the await! macro disappears I think this is our only hint. Will explore that path.

@cramertj
Copy link
Member

cramertj commented Mar 18, 2019

@gilescope IMO fixing this prior to moving to native syntax doesn't really make sense, because at that point I'm assuming we'll have an actual await node in the AST that doesn't become a yield until HIR lowering, which would make fixing this pretty trivial.

@estebank
Copy link
Contributor

We can create an intrinsic macro (like format) that only calls yield and poisons its span with CompilerDesugaringKind::Await. That way the generic yield error is still emitted except when calling await!().

bors added a commit that referenced this issue May 7, 2019
Implement built-in await syntax

Adds support for .await under the existing async_await feature gate.
Moves macro-like await! syntax to the await_macro feature gate.
Removes support for `await` as a non-keyword under the `async_await`
feature.

This new syntax is not final, but is the consensus solution proposed by the lang team, as explained in https://boats.gitlab.io/blog/post/await-decision/

Fix #51719
Fix #51751
Fix #60016
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-Polish Async-await issues that are part of the "polish" area P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants