Repository navigation
Mismatched types diagnostic for async fn return type trusts random returns over function signature #54326
Copy link
Copy link
Closed
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-frontendArea: Compiler frontend (errors, parsing and HIR)Area: Compiler frontend (errors, parsing and HIR)AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
With
#![feature(async_await, futures_api)]
async fn foo() -> i32 {
if false {
return Ok(6);
}
5
}the errors are:
error[E0308]: mismatched types
--> src/lib.rs:8:5
|
8 | 5
| ^ expected enum `std::result::Result`, found integral variable
|
= note: expected type `std::result::Result<{integer}, _>`
found type `{integer}`
error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == i32`
--> src/lib.rs:3:19
|
3 | async fn foo() -> i32 {
| ^^^ expected enum `std::result::Result`, found i32
|
= note: expected type `std::result::Result<{integer}, _>`
found type `i32`
= note: the return type of a function must have a statically known size
error: aborting due to 2 previous errors
It seems the compiler prefers to trust the return Ok(6) line over the function signature, so it ends up marking the function signature and the one return that matches that signature as errors.
In comparison, the diagnostic for regular non-async fns trusts the function signature and flags the return Ok(6) as the error.
fn foo() -> i32 {
if false {
return Ok(6);
}
5
}error[E0308]: mismatched types
--> src/lib.rs:3:16
|
3 | return Ok(6);
| ^^^^^ expected i32, found enum `std::result::Result`
|
= note: expected type `i32`
found type `std::result::Result<{integer}, _>`
error: aborting due to previous error
This latter diagnostic is much better since the user presumably wrote the function signature intentionally.
I hit this while refactoring a large async fn, and it took some time to figure out why the compiler kept insisting that the function should return a Result when I had no intention for it to do that - a stray early-return in the middle of the function that was returning an Ok().
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-frontendArea: Compiler frontend (errors, parsing and HIR)Area: Compiler frontend (errors, parsing and HIR)AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Activity
cramertj commentedon Sep 19, 2018
The code that lowers
async fnbody doesn't currently get passed the expected return type of the function, instead allowing it to be inferred. I'll take this one-- should be an easy fix.Edit: was not an easy fix-- what I had in mind would require duplicating the return type in the HIR, which is hard / not possible.
eddyb commentedon Sep 19, 2018
This shouldn't be solved during desugaring, IMO - we already handle closures nicely, e.g.:
The above example gets the nicer error - but if you put the closure in a variable before returning, you get the suboptimal pair of errors. For generators, even the below example gets the worse errors:
The logic for closures follows below (I think we should generalize it a bit and use it for generators):
rust/src/librustc_typeck/check/closure.rs
Lines 181 to 359 in 20dc0c5
nikomatsakis commentedon Mar 5, 2019
We decided that this bug is not blocking stabilization; confusing though it may be, it's not a severe enough "diagnostic fail" to block stabilization.
nikomatsakis commentedon Mar 5, 2019
Nonetheless, I've tagged this with E-needs-mentor because it seems eminently fixable, even if not a blocker.
Auto merge of #60592 - davidtwco:generator-signature-deduction, r=eddyb
davidtwco commentedon May 8, 2019
Current status of this after #60592 is in this Zulip topic.
richard-uk1 commentedon Nov 17, 2019
I've hit this today and was confused for a while. Here's a playground.
jonas-schievink commentedon Jan 24, 2020
This is not limited to closures/generators/async await but seems to occur generally with
impl Traitin return position:Additionally, the second note is wrong (
()isSized).This does not happen when changing the code to use a boxed trait instead (expected and found are in the right order).
nikomatsakis commentedon Jan 27, 2020
We actually solved the initial example given (playground):
gives
I think the case that @jonas-schievink is describing is pretty different. I moved it to #68561 and I'm closing this issue.