Skip to content

Silence unreachable code lint from await desugaring - #64930

Merged
bors merged 1 commit into
rust-lang:masterfrom
davidtwco:issue-61798-diverging-await
Oct 1, 2019
Merged

Silence unreachable code lint from await desugaring#64930
bors merged 1 commit into
rust-lang:masterfrom
davidtwco:issue-61798-diverging-await

Conversation

@davidtwco

Copy link
Copy Markdown
Member

Fixes#61798.

This PR silences the unreachable code lint when it originates from within an await desugaring.

This commit silences the unreachable code lint when it originates from
within a await desugaring.
Signed-off-by: David Wood <david@davidtw.co>
@rust-highfive

Copy link
Copy Markdown
Contributor

r? @petrochenkov

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfiverust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 30, 2019
@petrochenkov

Copy link
Copy Markdown
Contributor

@bors r+ rollup

@bors

bors commented Sep 30, 2019

Copy link
Copy Markdown
Collaborator

📌 Commit 870b47f has been approved by petrochenkov

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 30, 2019
@CentrilCentril added beta-nominated Nominated for backporting to the compiler in the beta channel. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 1, 2019
Centril added a commit to Centril/rust that referenced this pull request Oct 1, 2019
…it, r=petrochenkov
Silence unreachable code lint from await desugaring
Fixesrust-lang#61798.
This PR silences the unreachable code lint when it originates from within an await desugaring.
@CentrilCentril mentioned this pull request Oct 1, 2019
Centril added a commit to Centril/rust that referenced this pull request Oct 1, 2019
…it, r=petrochenkov
Silence unreachable code lint from await desugaring
Fixesrust-lang#61798.
This PR silences the unreachable code lint when it originates from within an await desugaring.
@CentrilCentril mentioned this pull request Oct 1, 2019
bors added a commit that referenced this pull request Oct 1, 2019
Rollup of 10 pull requests
Successful merges:
- #63674 (syntax: Support modern attribute syntax in the `meta` matcher)
- #63931 (Stabilize macros in some more positions)
- #64887 (syntax: recover trailing `|` in or-patterns)
- #64895 (async/await: improve not-send errors)
- #64896 (Remove legacy grammar)
- #64907 (A small amount of tidying-up factored out from PR #64648)
- #64928 (Add tests for some issues)
- #64930 (Silence unreachable code lint from await desugaring)
- #64935 (Improve code clarity)
- #64937 (Deduplicate closure type errors)
Failed merges:
r? @ghost
@bors
bors merged commit 870b47f into rust-lang:masterOct 1, 2019
@davidtwco
davidtwco deleted the issue-61798-diverging-await branch October 1, 2019 15:04
@pnkfelix

Copy link
Copy Markdown
Contributor

discussed at rustc mtg. accepted for beta backport.

@pnkfelixpnkfelix added the beta-accepted Accepted for backporting to the compiler in the beta channel. label Oct 3, 2019
@Mark-SimulacrumMark-Simulacrum removed the beta-nominated Nominated for backporting to the compiler in the beta channel. label Oct 22, 2019
bors added a commit that referenced this pull request Oct 24, 2019
[beta] backport rollup
This includes a bunch of PRs:
* Fix redundant semicolon lint interaction with proc macro attributes #64387
* Upgrade async/await to "used" keywords. #64875
* syntax: fix dropping of attribute on first param of non-method assocated fn #64894
* async/await: improve not-send errors #64895
* Silence unreachable code lint from await desugaring #64930
* Always mark rust and rust-call abi's as unwind #65020
* Account for macro invocation in `let mut $pat` diagnostic. #65123
* Ensure that associated `async fn`s have unique fresh param names #65142
* Add troubleshooting section to PGO chapter in rustc book. #65402
* Upgrade GCC to 8.3.0, glibc to 1.17.0 and crosstool-ng to 1.24.0 for dist-armv7-linux #65302
* Optimize `try_expand_impl_trait_type` #65293
* use precalculated dominators in explain_borrow #65172
* Fix ICE #64964#64989
bors added a commit that referenced this pull request Oct 26, 2019
[beta] backport rollup
This includes a bunch of PRs:
* Fix redundant semicolon lint interaction with proc macro attributes #64387
* Upgrade async/await to "used" keywords. #64875
* syntax: fix dropping of attribute on first param of non-method assocated fn #64894
* async/await: improve not-send errors #64895
* Silence unreachable code lint from await desugaring #64930
* Always mark rust and rust-call abi's as unwind #65020
* Account for macro invocation in `let mut $pat` diagnostic. #65123
* Ensure that associated `async fn`s have unique fresh param names #65142
* Add troubleshooting section to PGO chapter in rustc book. #65402
* Upgrade GCC to 8.3.0, glibc to 1.17.0 and crosstool-ng to 1.24.0 for dist-armv7-linux #65302
* Optimize `try_expand_impl_trait_type` #65293
* use precalculated dominators in explain_borrow #65172
* Fix ICE #64964#64989
* [beta] Revert "Auto merge of #62948 - matklad:failable-file-loading, r=petro… #65273
* save-analysis: Don't ICE when resolving qualified type paths in struct members #65353
* save-analysis: Nest tables when processing impl block definitions #65511
* Avoid ICE when checking `Destination` of `break` inside a closure #65518
* Avoid ICE when adjusting bad self ty #65755
* workaround msys2 bug #65762
tgross35 added a commit to tgross35/rust that referenced this pull request Jul 31, 2024
… r=fmease
Properly mark loop as diverging if it has no breaks
Due to specifics about the desugaring of the `.await` operator, HIR typeck doesn't recognize that `.await`ing an `impl Future<Output = !>` will diverge in the same way as calling a `fn() -> !`.
This is because the await operator desugars to approximately:
```rust
loop {
match future.poll(...) {
Poll::Ready(x) => break x,
Poll::Pending => {}
}
}
```
We know that the value of `x` is `!`, however since `break` is a coercion site, we coerce `!` to some `?0` (the type of the loop expression). Then since the type of the `loop {...}` expression is `?0`, we will not detect the loop as diverging like we do with other expressions that evaluate to `!`:
https://github.com/rust-lang/rust/blob/0b5eb7ba7bd796fb39c8bb6acd9ef6c140f28b65/compiler/rustc_hir_typeck/src/expr.rs#L240-L243
We can technically fix this in two ways:
1. Make coercion of loop exprs more eagerly result in a type of `!` when the only break expressions have type `!`.
2. Make loops understand that all of that if they have only diverging break values, then the loop diverges as well.
(1.) likely has negative effects on inference, and seems like a weird special case to drill into coercion. However, it turns out that (2.) is very easy to implement, we already record whether a loop has any break expressions, and when we do so, we actually skip over any break expressions with diverging values!:
https://github.com/rust-lang/rust/blob/0b5eb7ba7bd796fb39c8bb6acd9ef6c140f28b65/compiler/rustc_hir_typeck/src/expr.rs#L713-L716
Thus, we can consider the loop as diverging if we see that it has no breaks, which is the change implemented in this PR.
This is not usually a problem in regular code for two reasons:
1. In regular code, we already mark `break diverging()` as unreachable if `diverging()` is unreachable. We don't do this for `.await`, since we suppress unreachable errors within `.await` (rust-lang#64930). Un-suppressing this code will result in spurious unreachable expression errors pointing to internal await machinery.
3. In loops that truly have no breaks (e.g. `loop {}`), we already evaluate the type of the loop to `!`, so this special case is kinda moot. This only affects loops that have `break`s with values of type `!`.
Thus, this seems like a change that may affect more code than just `.await`, but it likely does not in meaningful ways; if it does, it's certainly correct to apply.
Fixesrust-lang#128434
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jul 31, 2024
… r=fmease
Properly mark loop as diverging if it has no breaks
Due to specifics about the desugaring of the `.await` operator, HIR typeck doesn't recognize that `.await`ing an `impl Future<Output = !>` will diverge in the same way as calling a `fn() -> !`.
This is because the await operator desugars to approximately:
```rust
loop {
match future.poll(...) {
Poll::Ready(x) => break x,
Poll::Pending => {}
}
}
```
We know that the value of `x` is `!`, however since `break` is a coercion site, we coerce `!` to some `?0` (the type of the loop expression). Then since the type of the `loop {...}` expression is `?0`, we will not detect the loop as diverging like we do with other expressions that evaluate to `!`:
https://github.com/rust-lang/rust/blob/0b5eb7ba7bd796fb39c8bb6acd9ef6c140f28b65/compiler/rustc_hir_typeck/src/expr.rs#L240-L243
We can technically fix this in two ways:
1. Make coercion of loop exprs more eagerly result in a type of `!` when the only break expressions have type `!`.
2. Make loops understand that all of that if they have only diverging break values, then the loop diverges as well.
(1.) likely has negative effects on inference, and seems like a weird special case to drill into coercion. However, it turns out that (2.) is very easy to implement, we already record whether a loop has any break expressions, and when we do so, we actually skip over any break expressions with diverging values!:
https://github.com/rust-lang/rust/blob/0b5eb7ba7bd796fb39c8bb6acd9ef6c140f28b65/compiler/rustc_hir_typeck/src/expr.rs#L713-L716
Thus, we can consider the loop as diverging if we see that it has no breaks, which is the change implemented in this PR.
This is not usually a problem in regular code for two reasons:
1. In regular code, we already mark `break diverging()` as unreachable if `diverging()` is unreachable. We don't do this for `.await`, since we suppress unreachable errors within `.await` (rust-lang#64930). Un-suppressing this code will result in spurious unreachable expression errors pointing to internal await machinery.
3. In loops that truly have no breaks (e.g. `loop {}`), we already evaluate the type of the loop to `!`, so this special case is kinda moot. This only affects loops that have `break`s with values of type `!`.
Thus, this seems like a change that may affect more code than just `.await`, but it likely does not in meaningful ways; if it does, it's certainly correct to apply.
Fixesrust-lang#128434
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Aug 1, 2024
Rollup merge of rust-lang#128443 - compiler-errors:async-unreachable, r=fmease
Properly mark loop as diverging if it has no breaks
Due to specifics about the desugaring of the `.await` operator, HIR typeck doesn't recognize that `.await`ing an `impl Future<Output = !>` will diverge in the same way as calling a `fn() -> !`.
This is because the await operator desugars to approximately:
```rust
loop {
match future.poll(...) {
Poll::Ready(x) => break x,
Poll::Pending => {}
}
}
```
We know that the value of `x` is `!`, however since `break` is a coercion site, we coerce `!` to some `?0` (the type of the loop expression). Then since the type of the `loop {...}` expression is `?0`, we will not detect the loop as diverging like we do with other expressions that evaluate to `!`:
https://github.com/rust-lang/rust/blob/0b5eb7ba7bd796fb39c8bb6acd9ef6c140f28b65/compiler/rustc_hir_typeck/src/expr.rs#L240-L243
We can technically fix this in two ways:
1. Make coercion of loop exprs more eagerly result in a type of `!` when the only break expressions have type `!`.
2. Make loops understand that all of that if they have only diverging break values, then the loop diverges as well.
(1.) likely has negative effects on inference, and seems like a weird special case to drill into coercion. However, it turns out that (2.) is very easy to implement, we already record whether a loop has any break expressions, and when we do so, we actually skip over any break expressions with diverging values!:
https://github.com/rust-lang/rust/blob/0b5eb7ba7bd796fb39c8bb6acd9ef6c140f28b65/compiler/rustc_hir_typeck/src/expr.rs#L713-L716
Thus, we can consider the loop as diverging if we see that it has no breaks, which is the change implemented in this PR.
This is not usually a problem in regular code for two reasons:
1. In regular code, we already mark `break diverging()` as unreachable if `diverging()` is unreachable. We don't do this for `.await`, since we suppress unreachable errors within `.await` (rust-lang#64930). Un-suppressing this code will result in spurious unreachable expression errors pointing to internal await machinery.
3. In loops that truly have no breaks (e.g. `loop {}`), we already evaluate the type of the loop to `!`, so this special case is kinda moot. This only affects loops that have `break`s with values of type `!`.
Thus, this seems like a change that may affect more code than just `.await`, but it likely does not in meaningful ways; if it does, it's certainly correct to apply.
Fixesrust-lang#128434
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beta-acceptedAccepted for backporting to the compiler in the beta channel.S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

unreachable_code warning when invoke .await on async diverging function

7 participants

@davidtwco@rust-highfive@petrochenkov@bors@pnkfelix@Centril@Mark-Simulacrum