Stream: wg-async-foundations

Topic: missing await diagnostic


Nathan Corbyn (Jun 19 2019 at 18:50, on Zulip):

Hello, I'm currently working on this issue https://github.com/rust-lang/rust/issues/61076 and in order to add the diagnostic I'm looking at including Future trait as a lang-item. A couple of people have mentioned that promoting an item to a lang-item is not normal just for a diagnostic; however, as the async/await syntax depends on the type it kind of makes sense to me that it should be a lang-item, but I really wasn't sure. If it were made a lang-item, the lang-item could be used throughout hir::lowering in place of the current paths into std which would be quite neat I think. I was wondering if anyone had any alternative/better ideas?

davidtwco (Jun 19 2019 at 19:04, on Zulip):

When I'm working on a diagnostic PR, if I feel the only way to proceed is to make something a lang item, then I normally do and it's never been a problem. If doing so would unblock you to continue, then I'd go ahead and if there are objections during review, we can work out an alternative approach then.

As I understand it, lang items can't be used during hir::lowering because things haven't been assigned DefIds yet, though I might be mistaken there.

davidtwco (Jun 19 2019 at 19:04, on Zulip):

Just my 2c.

Nathan Corbyn (Jun 19 2019 at 19:06, on Zulip):

Ahh okay I hadn't realised the thing about DefIds, thanks a lot!

Nathan Corbyn (Jun 19 2019 at 20:40, on Zulip):

So, I'm getting there, I just don't want to suggest .await in bodies that aren't async... Is there a way to check if a hir::BodyId is for an async body?

Taylor Cramer (Jun 19 2019 at 20:45, on Zulip):

@Nathan Corbyn you can use the BodyId to get the Body, which has a field called generator_kind that you can check (look for Some(hir::GeneratorKind::Async))

Nathan Corbyn (Jun 19 2019 at 20:46, on Zulip):

I actually can't find GeneratorKind...

Taylor Cramer (Jun 19 2019 at 20:54, on Zulip):

@Nathan Corbyn you'll need a relatively recent copy of rust-lang/rust

Taylor Cramer (Jun 19 2019 at 20:54, on Zulip):

like, from today

Taylor Cramer (Jun 19 2019 at 20:54, on Zulip):

or last night

Nathan Corbyn (Jun 19 2019 at 21:09, on Zulip):

Got it! Thanks

Taylor Cramer (Jun 19 2019 at 21:21, on Zulip):

@Nathan Corbyn sure thing!

Nathan Corbyn (Jun 19 2019 at 23:02, on Zulip):

(deleted)

Nathan Corbyn (Jun 20 2019 at 19:47, on Zulip):

I was using this to check if the body of a FnCtxt is async, but it causes an ICE:

let body_id = self.tcx().hir().body_owned_by(self.body_id);
let body = self.tcx().hir().krate().body(body_id);
if let Some(hir::GeneratorKind::Async) = body.generator_kind {
    // ...
}

I was wondering if anyone knew what was wrong with it?

(This is the ICE: error: internal compiler error: src/librustc/hir/map/mod.rs:455: body_owned_by: expr { take_u32(bar()) } (hir_id=HirId { owner: DefIndex(16), local_id: 8 }) has no associated body)

Taylor Cramer (Jun 20 2019 at 21:13, on Zulip):

what is self.body_id? it doesn't look like it's a valid hir_id mapping a node with an associated body

Taylor Cramer (Jun 20 2019 at 21:14, on Zulip):

today, body owners are consts, statics, fns, methods, and closures

Nathan Corbyn (Jun 20 2019 at 21:15, on Zulip):

It's a hir::HirId which is sort of confusing given the name

Matthew Jasper (Jun 20 2019 at 21:17, on Zulip):

You will want self.inh.body_id

Nathan Corbyn (Jun 20 2019 at 21:18, on Zulip):

Yeah I just spotted that, thanks!

Matthew Jasper (Jun 20 2019 at 21:30, on Zulip):

Actually, that looks like it's always the containing item, which is no help for a closure in an async fn.

Nathan Corbyn (Jun 20 2019 at 21:31, on Zulip):

Could you give an example of what you mean?

Matthew Jasper (Jun 20 2019 at 21:32, on Zulip):

async fn foo() { || { /* can't use .await here, but ihn.body_id would refer to the outer function */ } }

Nathan Corbyn (Jun 20 2019 at 21:33, on Zulip):

Ahh okay I see... This makes things complicated

Nathan Corbyn (Jun 20 2019 at 21:34, on Zulip):

I'm trying to work on an reasonably exhaustive list of edge cases like this so I can write a decent test

Matthew Jasper (Jun 20 2019 at 21:55, on Zulip):

So, body_id looks like the body's HirId when we're checking an item with a body. The correct thing is something like:

let item_id = self.tcx().hir().get_parent_node_by_hir_id(self.body_id);
if let Some(checked_body_id) = self.tcx().hir().maybe_body_owned_by(item_id);
    let body = self.tcx().hir().krate().body(body_id);
    if let Some(hir::GeneratorKind::Async) = body.generator_kind {
        // ...
    }
}
Nathan Corbyn (Jun 20 2019 at 21:56, on Zulip):

Thank you so much, I'll give it a try!

Nathan Corbyn (Jun 22 2019 at 22:16, on Zulip):

I'm just writing a test for this, should it go in the test/ui/async-await/await-keyword directory or the test/ui/suggestions directory?

davidtwco (Jun 23 2019 at 12:38, on Zulip):

I’d throw it in async-await but I don’t think it will matter that much.

Nathan Corbyn (Jun 30 2019 at 13:36, on Zulip):

I'm trying to extend this to work with chained expressions

Basically my idea so far is to introduce some logic here https://github.com/rust-lang/rust/blob/c06f80a3c6988d28db43f0cff3f35d9a005c3ad5/src/librustc_typeck/check/method/suggest.rs#L306 that will deal with the case that we're looking at a future; however, ideally, I only want to suggest adding .await in cases where awaiting would actually yield a type with the unresolved item (not really sure how to do this)

Is this overkill (i.e. should I just suggest in potentially appropriate places and use MaybeIncorrect), or does anyone know how to retry type-checking after applying a suggestion? (Or at least checking if a type has a given associated item)

Last update: Nov 18 2019 at 02:15UTC