-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Unhelpful "cannot infer type" error for ? in async block with unclear Result Err type #77880
Comments
Turning this into a closure gives a more helpful error:
|
@jyn514 Yeah, I found that several different code changes led to better errors. I'd guess part of the issue is that there's no stable way to add a type annotation directly to an async block. |
We should update the part of the code that emits the help text for closures (search for Maybe we can still print the type as in the closure case, just to point to the |
I'm willing to take a shot at this. @rustbot claim |
@hameerabbasi Are you still planning to work on this? |
Yes, I am, it fell off my radar. |
Ah, I recall what happened here. Here's the Zulip stream: https://rust-lang.zulipchat.com/#narrow/stream/187312-wg-async-foundations/topic/Picking.20up.20issue.20.20.2377880 Basically, I wasn't familiar enough with the internals of the compiler to fix this, unfortunately. |
I'm willing to work on this, but I'll unassign myself so it's more discoverable. @rustbot release-assignment |
It looks like there are a few factors here. One is that
The other is that the diagnostics code is oriented around identifying the type of a local variable or function parameter which can be annotated—even when the annotation which will be suggested doesn't involve that binding, like specifying the return type of a closure. This means that the type of an async block will never be described directly because in the desugaring it's wrapped in a fn may_error() -> Result<(), ()> { Err(()) }
fn consume_closure<T, F: Fn() -> T>(_: F) {}
fn f() {
consume_closure(|| {
may_error()?;
Ok(())
});
} Gives:
If the closure is assigned to a local variable before being passed to
I'm interested in trying to clean this up a bit. @rustbot claim. |
I’d assumed fixing this would involve making the diagnostics aware of generators, but I can’t actually see how much that could be leveraged for async blocks. After looking at this some more I can think of two things we can do here, neither of which are actually specific to async blocks. First, I think it could be helpful to have an additional note in general when inference fails for the Where possible, we can also suggest annotating another expression which would disambiguate the return type. This is actually already supported in some cases, like if a Result returned without Putting the suggestions together, the output for the initial example in this issue could be something like:
|
It looks like there are some good mismatched type diagnostics to piggyback off of. |
Both of these suggestions sound really nice, I hope we can implement them! |
…nversion-msg, r=davidtwco Enhance type inference errors involving the `?` operator This patch adds a special-cased note on type inference errors when the error span points to a `?` return. It also makes the primary label for such errors "cannot infer type of `?` error" in cases where before we would have only said "cannot infer type". One beneficiary of this change is async blocks, where we can't explicitly annotate the return type and so may not generate any other help (rust-lang#77880); this lets us at least print the error type we're converting from and anything we know about the type we can't fully infer. More generally, it signposts that an implicit conversion is happening that may have impeded type inference the user was expecting. We already do something similar for [mismatched type errors](https://github.com/rust-lang/rust/blob/2987785df3d46d5ff144a5c67fbb8f5cca798d78/src/test/ui/try-block/try-block-bad-type.stderr#L7). The check for a relevant `?` operator is built into the existing HIR traversal which looks for places that could be annotated to resolve the error. That means we could identify `?` uses anywhere in the function that output the type we can't infer, but this patch just sticks to adding the note if the primary span given for the error has the operator; if there are other expressions where the type occurs and one of them is selected for the error instead, it's more likely that the `?` operator's implicit conversion isn't the sole cause of the inference failure and that adding an additional diagnostic would just be noise. I added a ui test for one such case. The data about the `?` conversion is passed around in a `UseDiagnostic` enum that in theory could be used to add more of this kind of note in the future. It was also just easier to pass around than something with a more specific name. There are some follow-up refactoring commits for the code that generates the error label, which was already pretty involved and made a bit more complicated by this change.
Triage: nightly now gives
thanks to #80517 (thanks @wabain)! I think this means the issue is fixed. |
Minimal reproduction:
1.47.0 gives the following error:
Nightly gives a marginally more useful error:
I would expect an explanation of what type precisely couldn't be inferred, along with a pointer to the containing async block as the thing whose type couldn't be inferred.
rustc --version --verbose
(for 1.47.0):rustc --version --verbose
(for nightly):The text was updated successfully, but these errors were encountered: