Open
Description
Originally mentioned in this comment: #96373 (comment)
Essentially, semicolons after other diverging expressions are allowed. For example:
fn works() -> Result<bool, i32> {
return Err(1);
}
Here, the compiler is clever enough to note that because return Err(1)
always diverges, adding a semicolon after doesn't matter. However, the below code which is equivalent to this does not work properly:
fn breaks() -> Result<bool, i32> {
Err(1)?;
}
Here's a playground link containing the above two examples: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=af894bab48348897a421a9402856b71f
The exact compiler error:
error[[E0308]](https://doc.rust-lang.org/nightly/error-index.html#E0308): mismatched types
--> src/lib.rs:5:16
|
5 | fn breaks() -> Result<bool, i32> {
| ------ ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
6 | Err(1)?;
| - help: remove this semicolon to return this value
|
= note: expected enum `Result<bool, i32>`
found unit type `()`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
yeet
expressions (feature(yeet_expr)
) #96373andersk commentedon Jan 1, 2023
My understanding is that this is related to the fallback issues that have been preventing stabilization of the
!
type. See!
to a type (RFC 1216) #35121!
type #79366clarfonthey commentedon Jan 2, 2023
I was kind of afraid that's the case.
If this seems too separate from the existing issues for those, feel free to close it! Although I guess that this is another example that might be useful to test for.
aDotInTheVoid commentedon Jan 2, 2023
I'm not sure this is a bug,
gets desugared to
Unless you are relying on the compiler to eliminate the
Ok
branch as unreachable, which isn't guaranteed to happen, the whole expression isn't diverging (in the mind of the type system).I don't think the compiler should be required to do this elimination, as involving optimizations in exausiveness checks seems like it could get unintuitive fast, and expose many people to accidental breakage.
clarfonthey commentedon Jan 2, 2023
So, I would agree with this, except for the fact that the compiler could absolutely infer the type of
Err(1)
to beResult<!, i32>
and thus treat theOk
branch as diverging. But that leads into the!
fallback problems that were mentioned.est31 commentedon Jan 4, 2023
Related: rust-lang/style-team#165 (comment)
kadiwa4 commentedon Jan 5, 2023
Also related: feature
exhaustive_patterns
#51085WaffleLapkin commentedon Jun 13, 2024
So. Mrgh. This issue is indeed with the fallback.
This desugaring causes the type of the match to be inferred to
()
, due to the fallback issue. I would expect that this will start "working" in 2024 edition.Note however that I would highly advice against writing
Err(x)?
. The type ofOk
variant should no be inferred from the?
. IMO it's a bug in?
's desugaring. Similarly, allowing;
after diverging expressions is somewhat confusing. I was discussing with T-lang if we can break both of those things, but it did not cut the 2024 edition (and not yet decided that we actually want to break these things).traviscross commentedon Jun 14, 2024
As Waffle suggests, this is related to all of:
!
fall back to!
#123748